perm filename COMSCH.MSG[SCH,LSP]8 blob sn#807427 filedate 1986-01-29 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00301 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00043 00002	∂29-Nov-84  1009	RPG   	Comments on the Preliminary Report (2 pages)    
C00053 00003	∂30-Nov-84  1658	RPG   	Re: Kent Dybvig's Comments on Scheme  
C00060 00004	∂01-Dec-84  1049	RPG   	Kent Dybvig's Comments on Scheme 
C00065 00005	∂05-Dec-84  1353	RPG   	Re: Kent Dybvig's Comments on Scheme  
C00069 00006	∂07-Dec-84  1341	RPG   	[willc: preliminary report of workshop]    
C00104 00007	∂07-Dec-84  1342	RPG   	Slashification    
C00107 00008	∂09-Dec-84  1252	RPG   	MIN/MAX, DO/RETURN
C00109 00009	∂09-Dec-84  1304	RPG   	Re: critique of preliminary report    
C00131 00010	∂09-Dec-84  1307	RPG   	apology to Franz Lisp  
C00133 00011	∂10-Dec-84  1123	RPG   	Scheme conference report    
C00137 00012	∂10-Dec-84  1137	RPG   	Scheme conference report    
C00141 00013	∂10-Dec-84  1142	RPG   	Scheme conference report    
C00147 00014	∂12-Dec-84  1711	RPG   	Re:  Scheme conference report    
C00149 00015	∂12-Dec-84  1847	RPG  
C00151 00016	∂15-Dec-84  2257	RPG   	Scheme bibliography    
C00154 00017	∂16-Dec-84  2313	RPG   	continuation terminology    
C00157 00018	∂17-Dec-84  1524	RPG   	continuation terminology    
C00161 00019	∂18-Dec-84  2009	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Common Lisp order of evaluation    
C00163 00020	∂19-Dec-84  0850	@MIT-MC:rhh@MIT-VAX 	Re:  Common Lisp order of evaluation   
C00165 00021	∂19-Dec-84  0912	@MIT-MC:CPH@MIT-OZ 	Common Lisp order of evaluation    
C00166 00022	∂23-Dec-84  0901	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	length vs. list-length   
C00169 00023	∂23-Dec-84  2330	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	list-length
C00171 00024	∂24-Dec-84  1350	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	list-length
C00173 00025	∂28-Dec-84  1428	JAR@MIT-MC 	list-length  
C00174 00026	∂13-Jan-85  1322	JAR@MIT-MC 	list-length  
C00176 00027	∂13-Jan-85  1328	KMP@MIT-MC 	policy to adopt   
C00178 00028	∂13-Jan-85  2117	@MIT-MC:CPH@MIT-OZ 	Scheme String Operations: the Report    
C00217 00029	∂14-Jan-85  0217	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  policy to adopt
C00220 00030	∂15-Jan-85  1914	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Scheme String Operations: the Report   
C00226 00031	∂15-Jan-85  2339	@MIT-MC:CPH@MIT-OZ 	Scheme String Operations: the Report    
C00236 00032	∂24-Jan-85  1227	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Purpose of a "common" Scheme 
C00238 00033	∂31-Jan-85  0921	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Resources for Scheme course    
C00241 00034	∂01-Feb-85  0930	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	quotient, remainder, letrec  
C00243 00035	∂02-Feb-85  1040	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Scheme String Operations    
C00249 00036	∂03-Feb-85  1055	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  Scheme String Operations 
C00254 00037	∂03-Feb-85  1059	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	string->symbol, symbol->string
C00258 00038	∂04-Feb-85  0221	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Chez Scheme    
C00263 00039	∂05-Feb-85  1002	JAR@MIT-MC 	string->symbol, symbol->string   
C00269 00040	∂05-Feb-85  1007	JAR@MIT-MC 	Scheme String Operations    
C00271 00041	∂21-Feb-85  1259	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Draft delayed to 15 March    
C00273 00042	∂10-Mar-85  1716	@MIT-MC:GJS@MIT-EECS 	Numbers Committee Report    
C00309 00043	∂11-Mar-85  2110	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	I/O proposal  
C00335 00044	∂12-Mar-85  0940	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Re: Numbers Committee Report   
C00338 00045	∂12-Mar-85  0954	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Re: I/O proposal
C00341 00046	∂12-Mar-85  1306	@MIT-MC:GJS@MIT-OZ 	Re: Numbers Committee Report  
C00345 00047	∂12-Mar-85  1441	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
C00347 00048	∂12-Mar-85  1552	@MIT-MC:GJS@MIT-OZ 	Re: I/O proposal    
C00349 00049	∂14-Mar-85  1024	JAR@MIT-MC 	interaction of LOAD and CURRENT-INPUT-STREAM    
C00352 00050	∂14-Mar-85  1228	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: I/O proposal  
C00357 00051	∂15-Mar-85  0801	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
C00360 00052	∂16-Mar-85  1017	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
C00366 00053	∂16-Mar-85  1020	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
C00367 00054	∂17-Mar-85  0839	@MIT-MC:JINX@MIT-OZ 	I/O proposal  
C00374 00055	∂17-Mar-85  1027	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
C00378 00056	∂17-Mar-85  2041	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	assertions are better than types  
C00389 00057	∂17-Mar-85  2054	@MIT-MC:CPH@MIT-OZ 	assertions are better than types   
C00390 00058	∂17-Mar-85  2248	@MIT-MC:KMP@SCRC-STONY-BROOK 	assertions are better than types   
C00396 00059	∂18-Mar-85  1045	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
C00399 00060	∂18-Mar-85  1049	JAR@MIT-MC 	I/O proposal 
C00403 00061	∂18-Mar-85  1123	@MIT-MC:GJS@MIT-OZ 	Re:  I/O proposal   
C00405 00062	∂18-Mar-85  1159	@MIT-MC:GJS@MIT-OZ 	Re: assertions are better than types    
C00417 00063	∂18-Mar-85  1210	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Arithmetic overflow
C00420 00064	∂18-Mar-85  1545	@MIT-MC:linus!ramsdell@mitre-bedford 	Pointer-less stack allocated arrays. 
C00424 00065	∂18-Mar-85  2056	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Re: I/O proposal   
C00437 00066	∂19-Mar-85  0456	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 -- long message to scheme@mit-mc    
C00439 00067	∂19-Mar-85  0459	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 1
C00505 00068	∂19-Mar-85  0505	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 2
C00575 00069	∂19-Mar-85  0515	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 3
C00619 00070	∂19-Mar-85  1044	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Keyboard inputs    
C00625 00071	∂19-Mar-85  1445	@MIT-MC:JINX@MIT-OZ 	Keyboard inputs    
C00632 00072	∂19-Mar-85  2228	@MIT-MC:CPH@MIT-OZ 	Revisions to String Proposal  
C00642 00073	∂20-Mar-85  1254	JAR@MIT-MC 	Ports and streams 
C00649 00074	∂20-Mar-85  1542	@MIT-MC:KMP@SCRC-STONY-BROOK 	Ports and streams   
C00651 00075	∂21-Mar-85  1448	@MIT-MC:linus!ramsdell@mitre-bedford 	MAPC and MAPCAR  
C00654 00076	∂21-Mar-85  1449	@MIT-MC:linus!ramsdell@mitre-bedford 	Re: DRAFT of the Revised Revised Report   
C00659 00077	∂21-Mar-85  1554	@MIT-MC:JINX@MIT-OZ 	DRAFT of the Revised Revised Report    
C00664 00078	∂22-Mar-85  0951	JAR@MIT-MC 	(if a b)
C00666 00079	∂22-Mar-85  1322	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	ASSERT, ports, and NIL 
C00670 00080	∂22-Mar-85  1325	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Revisions to String Proposal 
C00672 00081	∂22-Mar-85  1344	@MIT-MC:GJS@MIT-OZ 	Re: ASSERT, ports, and NIL    
C00673 00082	∂22-Mar-85  1353	JAR@MIT-MC 	NIL
C00678 00083	∂22-Mar-85  1835	@MIT-MC:HUDAK@YALE.ARPA 	Re: DRAFT of the Revised Revised Report 
C00681 00084	∂22-Mar-85  2049	@MIT-MC:ANDY@SU-SCORE.ARPA 	Re: DRAFT of the Revised Revised Report   
C00683 00085	∂24-Mar-85  0007	@MIT-MC:CPH@MIT-OZ  
C00685 00086	∂24-Mar-85  0009	@MIT-MC:CPH@MIT-OZ 	Revisions to String Proposal  
C00687 00087	∂25-Mar-85  1306	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: NIL 
C00690 00088	∂25-Mar-85  1443	@MIT-MC:linus!ramsdell@mitre-bedford 	ITERATE
C00691 00089	∂25-Mar-85  1757	@MIT-MC:HUDAK@YALE.ARPA 	CAR and CDR again   
C00695 00090	∂25-Mar-85  1852	GJC@MIT-MC 	NIL, experience with VAX-NIL, or NIL is nothing to worry about.
C00699 00091	∂26-Mar-85  1439	@MIT-MC:linus!ramsdell@mitre-bedford 	WHEN   
C00700 00092	∂26-Mar-85  1444	@MIT-MC:linus!ramsdell@mitre-bedford 	LIST?  
C00702 00093	∂26-Mar-85  1501	@MIT-MC:linus!ramsdell@mitre-bedford 	function names.  
C00704 00094	∂26-Mar-85  1659	@MIT-MC:KMP@SCRC-STONY-BROOK 	function names.
C00712 00095	∂26-Mar-85  1703	@MIT-MC:KMP@SCRC-STONY-BROOK 	How to let macros work without defining what a macro is...  
C00719 00096	∂26-Mar-85  1802	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Missing CSNET messages 
C00721 00097	∂26-Mar-85  1839	@MIT-MC:GJS@MIT-OZ 	car/cdr   
C00723 00098	∂27-Mar-85  0212	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  DRAFT of the Revised Revised Report
C00727 00099	∂27-Mar-85  0638	@MIT-MC:JINX@MIT-OZ 	function names.    
C00729 00100	∂27-Mar-85  0709	@MIT-MC:JINX@MIT-OZ 	DRAFT of the Revised Revised Report    
C00733 00101	∂27-Mar-85  0722	@MIT-MC:JINX@MIT-OZ 	How to let macros work without defining what a macro is... 
C00735 00102	∂27-Mar-85  0727	@MIT-MC:JINX@MIT-OZ 	LIST? -- LIST 
C00737 00103	∂27-Mar-85  0808	GJC@MIT-MC 	plea for macros   
C00740 00104	∂27-Mar-85  1123	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: ASSERT, ports, and NIL  
C00745 00105	∂27-Mar-85  1140	@MIT-MC:ADAMS@YALE.ARPA 	Re:  DRAFT of the Revised Revised Report
C00747 00106	∂27-Mar-85  1143	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	Re: Draft of R.R. Report  
C00756 00107	∂27-Mar-85  1207	@MIT-MC:GJS@MIT-OZ 	flames!   
C00758 00108	∂27-Mar-85  1242	@MIT-MC:JINX@MIT-OZ 	ASSERT, ports, and NIL  
C00760 00109	∂27-Mar-85  1245	@MIT-MC:JINX@MIT-OZ 	Draft of R.R. Report    
C00763 00110	∂27-Mar-85  1644	@MIT-MC:linus!ramsdell@mitre-bedford 	Scheme names
C00766 00111	∂27-Mar-85  1726	JAR@MIT-MC 	NIL, again   
C00772 00112	∂28-Mar-85  0611	@MIT-MC:KMP@SCRC-STONY-BROOK 	How to let macros work without defining what a macro is...  
C00780 00113	∂28-Mar-85  0717	@MIT-MC:HUDAK@YALE.ARPA 	IF and WHEN    
C00782 00114	∂28-Mar-85  0753	@MIT-MC:JINX@MIT-OZ 	IF and WHEN   
C00783 00115	∂28-Mar-85  0803	@MIT-MC:JINX@MIT-OZ 	syntax-expand 
C00785 00116	∂28-Mar-85  1303	@MIT-MC:HUDAK@YALE.ARPA 	Re: IF and WHEN
C00787 00117	∂28-Mar-85  1437	@MIT-MC:linus!ramsdell@mitre-bedford 	Other names for ITERATE    
C00789 00118	∂28-Mar-85  1511	@MIT-MC:JINX@MIT-OZ 	Other names for ITERATE 
C00791 00119	∂28-Mar-85  2248	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  flames!   
C00793 00120	∂29-Mar-85  0713	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	ITERATE, DEFINE and CELLs 
C00797 00121	∂29-Mar-85  0759	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  Other names for ITERATE  
C00799 00122	∂29-Mar-85  0851	@MIT-MC:GJS@MIT-OZ 	WHEN, UNLESS, RECURSE, et. al.
C00801 00123	∂29-Mar-85  0949	@MIT-MC:JINX@MIT-OZ 	ITERATE, DEFINE and CELLs    
C00810 00124	∂29-Mar-85  0957	@MIT-MC:JINX@MIT-OZ 	WHEN, UNLESS, RECURSE, et. al.    
C00811 00125	∂29-Mar-85  1214	JAR@MIT-MC 	ITERATE, DEFINE, WHEN, cells, etc.    
C00816 00126	∂29-Mar-85  1238	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	names    
C00820 00127	∂29-Mar-85  1537	@MIT-MC:linus!ramsdell@mitre-bedford 	REC and LETREC   
C00822 00128	∂29-Mar-85  1540	@MIT-MC:linus!ramsdell@mitre-bedford 	rationalized names    
C00824 00129	∂29-Mar-85  1545	@MIT-MC:linus!ramsdell@mitre-bedford 	LIST?  
C00826 00130	∂29-Mar-85  1631	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Other names for ITERATE   
C00828 00131	∂29-Mar-85  2135	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	NIL vs ()    
C00830 00132	∂29-Mar-85  2138	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	RE: The revised revised Report   
C00836 00133	∂30-Mar-85  0047	@MIT-MC:CPH@MIT-OZ 	ITERATE, DEFINE and CELLs
C00839 00134	∂30-Mar-85  0054	@MIT-MC:CPH@MIT-OZ 	The revised revised Report    
C00841 00135	∂31-Mar-85  1822	JAR@MIT-MC 	REC and LETREC    
C00843 00136	∂31-Mar-85  1834	JAR@MIT-MC 	READ-CHAR-READY?  
C00845 00137	∂31-Mar-85  2042	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	REC and LETREC  
C00847 00138	∂31-Mar-85  2045	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	JINX reply on RECUR, DEFINE, ...    
C00854 00139	∂31-Mar-85  2047	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	CPH reply on DEFINE  
C00857 00140	∂01-Apr-85  2047	JAR@MIT-MC 	CPH reply on DEFINE    
C00860 00141	∂02-Apr-85  0005	@MIT-MC:CPH@MIT-OZ 	CPH reply on DEFINE 
C00862 00142	∂09-Apr-85  0637	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	First Class Environments and Their Extenders
C00870 00143	∂10-Apr-85  0107	@MIT-MC:CPH@MIT-OZ 	First Class Environments and Their Extenders 
C00872 00144	∂21-Apr-85  0652	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	if, mapcar, mapc, ...   
C00880 00145	∂21-Apr-85  0654	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	lexical syntax for numbers   
C00888 00146	∂21-Apr-85  1444	@MIT-MC:rhh@MIT-VAX 	reactions to Will's updates  
C00891 00147	∂21-Apr-85  1923	@MIT-MC:JINX@MIT-OZ 	lexical syntax for numbers   
C00893 00148	∂21-Apr-85  1927	@MIT-MC:JINX@MIT-OZ 	reactions to Will's updates  
C00895 00149	∂21-Apr-85  1929	@MIT-MC:CPH@MIT-OZ 	lexical syntax for numbers    
C00897 00150	∂21-Apr-85  1931	@MIT-MC:CPH@MIT-OZ 	reactions to Will's updates   
C00899 00151	∂22-Apr-85  1103	JAR@MIT-MC 	hashing 
C00902 00152	∂22-Apr-85  1117	JAR@MIT-MC 	hashing 
C00906 00153	∂22-Apr-85  1226	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	mapcar and mapc    
C00908 00154	∂22-Apr-85  1302	@MIT-MC:rhh@MIT-VAX 	Re:  hashing  
C00910 00155	∂22-Apr-85  1544	@MIT-MC:linus!ramsdell@mitre-bedford 	Two armed IF is essential. 
C00912 00156	∂22-Apr-85  1547	@MIT-MC:linus!ramsdell@mitre-bedford 	REC => LABEL
C00913 00157	∂23-Apr-85  0912	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	Retraction and Resubmission  
C00918 00158	∂23-Apr-85  1336	JAR@MIT-MC 	Two armed IF is essential.  
C00920 00159	∂24-Apr-85  1541	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	two-armed if (oops)
C00922 00160	∂25-Apr-85  0902	@MIT-MC:rhh@MIT-VAX 	number exponent syntax  
C00924 00161	∂26-Apr-85  0037	JAR@MIT-MC 	number exponent syntax 
C00926 00162	∂26-Apr-85  0351	@MIT-MC:rhh@MIT-VAX 	Re:  number exponent syntax  
C00928 00163	∂21-Jun-85  1631	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@csnet-relay.arpa 	lcm
C00931 00164	∂21-Jun-85  1723	@MIT-MC.ARPA:ANDY@SU-SUSHI.ARPA 	Re: lcm
C00933 00165	∂09-Jul-85  2145	@MIT-MC.ARPA:ALTMAN%ti-csl.csnet@csnet-relay.arpa 	Scheme Benchmark Programs Sought  
C00936 00166	∂09-Jul-85  2325	@MIT-MC.ARPA:mw%brandeis.csnet@csnet-relay.arpa 	What cr*p  
C00938 00167	∂11-Jul-85  2016	GJC@MIT-MC.ARPA 	What cr*p    
C00940 00168	∂19-Jul-85  1756	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford 	CSI Lisp is not tail recursive  
C00943 00169	∂20-Jul-85  0350	GJC@MIT-MC.ARPA 	truth in advertisement 
C00947 00170	∂22-Jul-85  1043	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	truth in advertisement 
C00949 00171	∂22-Jul-85  1522	GJC@MIT-MC.ARPA 	truth in advertisement 
C00951 00172	∂24-Jul-85  1622	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford    
C00954 00173	∂24-Jul-85  1929	@MIT-MC.ARPA:OXLEY%ti-csl.csnet@csnet-relay.arpa 	Scheme Not Tail Recursive!!!????   
C00957 00174	∂24-Jul-85  1944	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@csnet-relay.arpa 	Re: Scheme Not Tail Recursive!!!????  
C00961 00175	∂25-Jul-85  0342	@MIT-MC.ARPA:GJS@MIT-OZ 	Re: Scheme Not Tail Recursive!!!????    
C00963 00176	∂25-Jul-85  1115	JAR@MIT-MC.ARPA 	Are fluids objects?    
C00966 00177	∂25-Jul-85  1125	@MIT-MC.ARPA:JINX@MIT-OZ 	Scheme Not Tail Recursive!!!????  
C00970 00178	∂25-Jul-85  1310	@MIT-MC.ARPA:JINX@MIT-OZ 	previous message   
C00971 00179	∂26-Jul-85  1444	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Scheme Not Tail Recursive!!!????  
C00973 00180	∂26-Jul-85  2251	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Ambiguous number syntax
C00975 00181	∂27-Jul-85  1715	@MIT-MC.ARPA:GJS@MIT-OZ 	Re: Ambiguous number syntax   
C00978 00182	∂29-Jul-85  1020	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Re: Ambiguous number syntax 
C00983 00183	∂30-Jul-85  2036	GJC@MIT-MC.ARPA 	Ambiguous number syntax
C00984 00184	∂31-Jul-85  1159	@MIT-MC.ARPA:CPH@MIT-OZ 	identifiers and symbols  
C00988 00185	∂31-Jul-85  1445	JAR@MIT-MC.ARPA 	identifiers and symbols
C00994 00186	∂01-Aug-85  0915	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: identifiers and symbols 
C00998 00187	∂02-Aug-85  1338	@MIT-MC.ARPA:mw%brandeis.csnet@csnet-relay.arpa 	Re: identifiers and symbols    
C01004 00188	∂05-Aug-85  1836	@MIT-MC.ARPA:unc!dyb%unc.csnet@csnet-relay.arpa 	Re: identifiers and symbols    
C01011 00189	∂05-Aug-85  1851	@MIT-MC.ARPA:CPH@MIT-OZ 	identifiers and symbols  
C01015 00190	∂09-Aug-85  1539	JAR@MIT-MC.ARPA 	Altering quoted structure   
C01018 00191	∂09-Aug-85  1546	JAR@MIT-MC.ARPA 	(EQV? #\? #\?) ?  
C01019 00192	∂09-Aug-85  1549	JAR@MIT-MC.ARPA 	Altering quoted structure, addendum   
C01021 00193	∂09-Aug-85  1618	@MIT-MC.ARPA:JINX@MIT-OZ 	(EQV? #\? #\?) ?   
C01022 00194	∂09-Aug-85  1623	@MIT-MC.ARPA:JINX@MIT-OZ 	Altering quoted structure    
C01024 00195	∂12-Aug-85  0745	JAR@MIT-MC.ARPA 	delay, force, cons-stream   
C01025 00196	∂16-Sep-85  1306	JAR@MIT-MC.ARPA 	report scheme in CL trace 
C01029 00197	∂17-Sep-85  1312	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  report scheme in CL trace    
C01032 00198	∂22-Oct-85  2253	@MIT-MC.ARPA:meltsner%athena@mit-eddie.MIT.EDU 	Scheme for Thermo.    
C01036 00199	∂22-Oct-85  2253	JAR@MIT-MC.ARPA 	scheme implementations 
C01039 00200	∂22-Oct-85  2334	JAR@MIT-MC.ARPA 	welcome 
C01042 00201	∂22-Oct-85  2351	JAR@MIT-MC.ARPA 	Implementation blurb: Scheme in Common Lisp
C01045 00202	∂23-Oct-85  2107	JAR@MIT-MC.ARPA 	Implementation blurb: Vincennes Scheme
C01047 00203	∂23-Oct-85  2322	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Elementary question about backquote in T.   
C01050 00204	∂24-Oct-85  0856	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Elementary question about backquote in T.  
C01055 00205	∂24-Oct-85  1201	@MIT-MC.ARPA:RAM@YALE.ARPA 	Re: Elementary question about backquote in T.  
C01060 00206	∂24-Oct-85  1331	JAR@MIT-MC.ARPA 	T mailing lists.  
C01062 00207	∂24-Oct-85  1443	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Q. on backquote    
C01064 00208	∂25-Oct-85  0945	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: Q. on backquote 
C01066 00209	∂26-Oct-85  1019	@MIT-MC.ARPA:WAXMAN@USC-ECL.ARPA 	PLASE REMOVE MY NAME FROM SCHEME MAILING LIST 
C01067 00210	∂28-Oct-85  0740	JAR@MIT-MC.ARPA 	moderation   
C01070 00211	∂28-Oct-85  0824	JAR@MIT-MC.ARPA 	implementations   
C01077 00212	∂28-Oct-85  1024	JAR@MIT-MC.ARPA 	implementations   
C01084 00213	∂28-Oct-85  1158	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Re: moderation
C01087 00214	∂28-Oct-85  1359	@MIT-MC.ARPA:bap@g.cs.cmu.edu 	Re: need for quoting in Lisp 
C01093 00215	∂28-Oct-85  1441	GJC@MIT-MC.ARPA
C01097 00216	∂28-Oct-85  1457	GJC@MIT-MC.ARPA 	moderation   
C01099 00217	∂28-Oct-85  1542	@MIT-MC.ARPA:JINX@MIT-OZ 	moderation    
C01104 00218	∂28-Oct-85  1627	@MIT-MC.ARPA:HAL@MIT-OZ 	quote
C01110 00219	∂28-Oct-85  1720	@MIT-MC.ARPA:SRIDHARAN@BBNG.ARPA 	Why quote? 
C01115 00220	∂28-Oct-85  1816	@MIT-MC.ARPA:JINX@MIT-OZ 	quote    
C01117 00221	∂29-Oct-85  0816	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Re: need for quoting in Lisp
C01120 00222	∂29-Oct-85  0842	JAR@MIT-MC.ARPA 	administrivia
C01122 00223	∂29-Oct-85  1231	@MIT-MC.ARPA:cpd@LOCUS.UCLA.EDU 	Continuations    
C01124 00224	∂30-Oct-85  0750	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: moderation 
C01127 00225	∂30-Oct-85  0909	@MIT-MC.ARPA:cpd@LOCUS.UCLA.EDU 	Re: Continuations
C01132 00226	∂30-Oct-85  1206	@MIT-MC.ARPA:JINX@MIT-OZ 	Continuations 
C01136 00227	∂30-Oct-85  1351	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	will the real current continuation please stand up
C01139 00228	∂30-Oct-85  1410	JAR@MIT-MC.ARPA 	Continuations
C01142 00229	∂30-Oct-85  1503	JAR@MIT-MC.ARPA 	will the real current continuation please stand up   
C01144 00230	∂30-Oct-85  1800	@MIT-MC.ARPA:JINX@MIT-OZ 	will the real current continuation please stand up    
C01147 00231	∂30-Oct-85  1827	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: will the real current continuation please stand up 
C01149 00232	∂31-Oct-85  1024	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Scheme Implementation Blurb:  Chez Scheme
C01154 00233	∂01-Nov-85  1351	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: will the real current continuation please stand up 
C01157 00234	∂08-Nov-85  1809	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Syntactic extensions to Scheme   
C01160 00235	∂12-Nov-85  1334	@MIT-MC.ARPA:OXLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	PC Scheme Implementation Information    
C01168 00236	∂12-Nov-85  1905	JAR@MIT-MC.ARPA 	test message 
C01169 00237	∂13-Nov-85  1618	JAR@MIT-MC.ARPA 	a modest backquote proposal 
C01176 00238	∂14-Nov-85  1020	JAR@MIT-MC.ARPA 	Syntactic extensions to Scheme   
C01194 00239	∂14-Nov-85  1559	@MIT-MC.ARPA:JINX@MIT-OZ 	Syntactic extensions to Scheme (long message)    
C01202 00240	∂14-Nov-85  2150	@MIT-MC.ARPA:CPH@MIT-OZ 	Syntactic extensions to Scheme
C01214 00241	∂15-Nov-85  1251	JAR@MIT-MC.ARPA 	testing, testing, ...  
C01216 00242	∂17-Nov-85  1547	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford.ARPA 	Stream command processing (long message)  
C01230 00243	∂18-Nov-85  1710	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford.ARPA 	read-cstream fix 
C01232 00244	∂18-Nov-85  1744	@MIT-MC.ARPA:JINX@MIT-OZ 	Stream command processing (long message)    
C01234 00245	∂18-Nov-85  1828	@MIT-MC.ARPA:JINX@MIT-OZ 	Stream command processing (long message)    
C01238 00246	∂18-Nov-85  1846	@MIT-MC.ARPA:JINX@MIT-OZ 	Incomplete message 
C01239 00247	∂19-Nov-85  1327	JAR@MIT-MC.ARPA 	backquote proposal
C01242 00248	∂20-Nov-85  0901	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: backquote proposal 
C01244 00249	∂20-Nov-85  1214	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  backquote proposal   
C01247 00250	∂20-Nov-85  1326	JAR@MIT-MC.ARPA 	backquote proposal
C01252 00251	∂20-Nov-85  1333	JAR@MIT-MC.ARPA 	Backquote algorithm    
C01259 00252	∂20-Nov-85  1743	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Multiple LAMBDA evaluations 
C01262 00253	∂20-Nov-85  2352	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	trace   
C01266 00254	∂21-Nov-85  0745	@MIT-MC.ARPA:JINX@MIT-OZ 	trace    
C01271 00255	∂21-Nov-85  0903	JAR@MIT-MC.ARPA 	description of MacScheme    
C01275 00256	∂21-Nov-85  0920	JAR@MIT-MC.ARPA 	Multiple LAMBDA evaluations 
C01280 00257	∂21-Nov-85  1306	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	re:  backquote  
C01282 00258	∂21-Nov-85  1324	JAR@MIT-MC.ARPA 	trace   
C01286 00259	∂21-Nov-85  1324	@MIT-MC.ARPA:CPH@MIT-OZ 	trace
C01288 00260	∂21-Nov-85  1324	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
C01290 00261	∂21-Nov-85  1805	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	EQ? and procedures, numbers, etc 
C01293 00262	∂21-Nov-85  1926	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: Multiple LAMBDA evaluations  
C01297 00263	∂21-Nov-85  2015	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
C01300 00264	∂22-Nov-85  1054	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: Multiple LAMBDA evaluations  
C01305 00265	∂22-Nov-85  1135	@MIT-MC.ARPA:KMP@SCRC-STONY-BROOK.ARPA 	EQ? and procedures, numbers, etc   
C01311 00266	∂22-Nov-85  1515	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? and procedures, numbers, etc 
C01316 00267	∂22-Nov-85  1628	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	Re: trace    
C01320 00268	∂22-Nov-85  2038	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re: backquote proposal    
C01322 00269	∂22-Nov-85  2101	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
C01325 00270	∂22-Nov-85  2157	@MIT-MC.ARPA:JINX@MIT-OZ 	trace    
C01330 00271	∂25-Nov-85  1133	@MIT-MC.ARPA:KMP@SCRC-STONY-BROOK.ARPA 	EQ? and procedures, numbers, etc   
C01335 00272	∂25-Nov-85  1426	@MIT-MC.ARPA:JINX@MIT-OZ 	EQ? and procedures, numbers, etc  
C01337 00273	∂25-Nov-85  1551	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	trace, language vs. implementation    
C01342 00274	∂25-Nov-85  1802	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	Re: trace    
C01348 00275	∂25-Nov-85  1812	@MIT-MC.ARPA:JINX@MIT-OZ 	trace, language vs. implementation
C01354 00276	∂26-Nov-85  0049	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	EQ? and procedures etc 
C01372 00277	∂26-Nov-85  0953	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? and procedures etc 
C01387 00278	∂26-Nov-85  1201	JAR@MIT-MC.ARPA 	EQV? and procedures etc
C01391 00279	∂27-Nov-85  2057	@MIT-MC.ARPA:wagle%indiana.csnet@CSNET-RELAY.ARPA 	EQ? on pointers to functions 
C01397 00280	∂04-Dec-85  1518	@MIT-MC.ARPA:msr@rice.ARPA 	Query: Scheme on a Sun?    
C01398 00281	∂12-Dec-85  1515	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	[Postmaster@SCRC-STONY-BROOK.ARPA: Unable to deliver letter]   
C01403 00282	∂13-Dec-85  1355	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? again, already
C01406 00283	∂13-Dec-85  1850	JAR@MIT-MC.ARPA 	EQ? again, already
C01411 00284	∂13-Dec-85  1854	JAR@MIT-MC.ARPA 	EQ? again, already
C01412 00285	∂14-Dec-85  0603	@MIT-MC.ARPA:HAL@MIT-OZ 	intro computer science course at Brandeis    
C01438 00286	∂15-Dec-85  1641	JAR@MIT-MC.ARPA 	[CPH%MIT-OZ: HP 300s]  
C01441 00287	∂15-Dec-85  1919	JAR@MIT-MC.ARPA 	backquote    
C01448 00288	∂20-Dec-85  1153	@MC.LCS.MIT.EDU:CPH@OZ.AI.MIT.EDU 	Editors used with Scheme 
C01450 00289	∂20-Dec-85  1153	@MC.LCS.MIT.EDU:duke@mitre.ARPA 	Editors used with Scheme   
C01452 00290	∂21-Jan-86  1150	@MC.LCS.MIT.EDU:marick%fang@gswd-vms 	Industrial-strength Scheme class.    
C01455 00291	∂21-Jan-86  1446	@MC.LCS.MIT.EDU:HAL%OZ.AI.MIT.EDU@XX.LCS.MIT.EDU 	Industrial-strength Scheme class.  
C01457 00292	∂23-Jan-86  1301	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  Industrial-strength Scheme class.
C01461 00293	∂24-Jan-86  0827	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	quasiquote implementation   
C01466 00294	∂24-Jan-86  1252	JAR@MC.LCS.MIT.EDU 	quasiquote implementation
C01468 00295	∂25-Jan-86  1155	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  quasiquote implementation   
C01475 00296	∂28-Jan-86  1108	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Of growing code and diminishing hacks...    
C01481 00297	∂28-Jan-86  2352	@MC.LCS.MIT.EDU:Miller.pa@Xerox.COM 	Re: Of growing code and diminishing hacks...    
C01483 00298	∂29-Jan-86  0121	@MC.LCS.MIT.EDU:Miller.pa@Xerox.COM 	Re: Of growing code and diminishing hacks...    
C01485 00299	∂29-Jan-86  0558	GJC@MC.LCS.MIT.EDU 	Overloading of empty list as false.
C01489 00300	∂29-Jan-86  1049	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Re: Of growing code and diminishing hacks...
C01492 00301	∂29-Jan-86  1119	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Re: Of growing code and diminishing hacks...
C01494 ENDMK
C⊗;
∂29-Nov-84  1009	RPG   	Comments on the Preliminary Report (2 pages)    
 ∂28-Nov-84  0331	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Comments on the Preliminary Report (2 pages) 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Nov 84  03:31:05 PST
Received: from unc by csnet-relay.csnet id a021839; 28 Nov 84 6:30 EST
Received: by unc (4.12/4.7) id AA17493; Tue, 27 Nov 84 23:00:58 est
Date: Tue, 27 Nov 84 23:00:58 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8411280400.AA17493@unc>
To: scheme@mit-mc.ARPA
Subject: Comments on the Preliminary Report (2 pages)
Cc: willc%indiana.csnet@csnet-relay.arpa

Comments on Essential Scheme


These  comments are arranged in four categories:  lambda  syntax,  other 
special forms,  functions,  and lexical matters.   I feel quite strongly 
about  the issues I outline here.   I have other minor gripes (don't  we 
all)  that  I didn't bother to include here,  for fear they would  water 
down the substantive issues.


Lambda Syntax

For  several  years  my  Scheme  system has  had  a  syntax  for  lambda 
expressions  that  allows naming of the closure within the body  of  the 
closure for enhanced readability and efficiency.  The syntax is:
     (lambda name formals . body)
where  name  is  a symbol bound lexically to the  closure  within  body, 
formals  is a list of formal parameters,  and body is a set of  zero  or 
more  forms to execute.   Name may be omitted and there is no  ambiguity 
since formals is always a list.

This  feature,  which  I  have called "named  lambda,"  allows  terse, 
referentially transparent recursive function definitions.  It is similar 
to  the optional "rec," special form,  but is shorter and perhaps more 
easily  optimized  than  rec.   It is quite a  bit  shorter  than  using 
"letrec."  For example, the boring factorial function looks like:
     (lambda fact (x) (if (= x 0) 1 (* x (fact (- x 1))))),
a totally self contained definition.

Named  lambda generalizes to named let,  something which seems  to  have 
appeared elsewhere independently.  It looks like:
     (let name ((x1 v1) (x2 v2) ...) . body),
where name may again be omitted.  It translates into:
     ((lambda name (x1 x2 ...) . body) v1 v2 ...),
and replaces the old iterate expression.

Unfortunately,  the partial destructuring provided by the adopted lambda 
syntax conflicts with the named lambda syntax,  introducing an ambiguity 
in some cases, as in:
     (lambda f (g x) ...).
Is  this  a named lambda with two formals or an unnamed  lambda  with  a 
single &rest formal?

The  partial  destructuring syntax is merely a different syntax for  the 
&rest formal parameter adopted by Common Lisp.   The only benefit to  be 
gained  by not using the Common Lisp syntax is that some implementations 
might generalize to full destructuring.   I think it more likely that we 
would want to generalize to optional arguments.   Why not just use  part 
of the syntax adopted by Common Lisp?   For now, we could make the &rest 
syntax required and the &optional syntax optional.

If  everyone dislikes the &rest syntax then I think we ought to  resolve 
the  ambiguity  with named lambda by requiring the name to  be  present.  
This   would  improve  code  readability  and  facilitate   optimization 
regardless of the system the code is executed on.


Other Special Forms

1.   The "if" special form should require an else part.  This allows the 
compiler/interpreter  to  make a sanity check for the user  which  might 
save  some  grief,  and seems a little cleaner.   The macros "when"  and 
"unless" are the appropriate way to express the intended meaning.

2.   Block is a much better name for the statement grouping special form 
than  "begin".   Do  we really need an artifact of Algol syntax  in  our 
language?   After  all,  it  is a block of code,  not a begin  of  code.  
(If  someone  is worried about clashing with a process blocking  function 
they should name their function "block-process.")

3.   Case expressions should allow single keys without putting them in a 
list.   The  user rarely wants the single key to be a list (eq semantics 
and all),  so there really isn't any ambiguity.   Since single keys  are 
probably the most common, case expressions will be less bulky.
For example,
     (case x ((a) ...) ((b) ...) ((c d) ...) (else ...))
would simply be
     (case x (a ...) (b ...) ((c d) ...) (else ...)).


Functions

1.   Call/cc should be an alternative to call-with-current-continuation.  
How  are we ever going to get people to feel comfortable with  something 
so  imposing that it requires 30 keystrokes to type in and takes up half 
a line?

2.   Transcendental functions should be required only in implementations 
with  floating point numbers,  not just any implementation with  numbers 
other than integers.   In particular, an implementation with rational or 
interval  arithmetic  should not be bound to  supporting  transcendental 
functions.  (This was probably just a misstatement in Will's note.)

3.   The  length function should be generic,  returning a value for  all 
reasonable  arguments.   There  can still be individual functions  list-
length, string-length, vector-length, and so on.


Lexical Matters

Scheme systems should be case sensitive.   Let's not forget that symbols 
have  other  uses  than as Scheme identifiers.   How  can  we  implement 
prolog-like  variables  in  Scheme without being able  to  differentiate 
between  upper and lower case letters within the symbols?   Does  anyone 
really   still  use  an  upper-case  only   terminal?    Assuming   case 
sensitivity,  all  standard Scheme functions and special forms should be 
written with entirely lower-case letters.

∂30-Nov-84  1658	RPG   	Re: Kent Dybvig's Comments on Scheme  
 ∂30-Nov-84  1545	@MIT-MC:bartley%ti-csl.csnet@csnet-relay.arpa 	Re: Kent Dybvig's Comments on Scheme  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Nov 84  15:44:40 PST
Received: from ti-csl by csnet-relay.csnet id a008334; 30 Nov 84 18:12 EST
Date: 30 Nov 1984 1147-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: Kent Dybvig's Comments on Scheme
To: Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa


Re:    Kent Dybvig's comments on the preliminary report on Scheme

    I'd like to briefly add my "votes" on Kent's suggestions and bring up
    some additional complexities in the issues he raised.

Lambda Syntax

    I prefer (REC name (LAMBDA args . body)) first, then MIT-style
    NAMED-LAMBDA second.  (I support both.)  Will's discussion summarizes
    my reasons quite well.  We should NOT require all lambdas to be named.

IF without else part

    I would not mind requiring WHEN in this case, making (IF a b)
    syntactically incorrect.  This allows better compile-time checking.  I
    use WHEN myself to make this distinction and find it useful.  BTW, I do
    NOT find UNLESS useful, since (WHEN (NOT ..)..) usually reads better.

BLOCK vs BEGIN vs LET()

    As Will points out, the real question is whether the construct we have
    in mind is a compound expression or an Algol-like block containing both
    declarations and expressions to be evaluated.  I prefer BEGIN for the
    former and LET for the latter.

    The problem is that Will suggests (paraphrasing someone else) that
    (BEGIN ...) might be equivalent to (LET () ...).  I have conflicting
    thoughts on this.  Pro: if they are the same, then I would vote to
    remove BEGIN from the (essential) language as hopelessly redundant with
    LET.  Con: early papers by Steele and Sussman treat (BEGIN a b) as a
    macro for ((LAMBDA (ignored-id) b) a), which is equivalent to
    (LET ((ignored-id a)) b).  Thus, BEGIN already is a scope-extending
    operation.

    This has the following practical consequence.  What is the scope of FOO
    in the following?

	(define (f ...)
	   (define g ...)
	   (begin
	      (define foo ...))
	   body)

    I understand that MIT Scheme "promotes" both G and FOO directly under
    F.  This hack is needed for macros that expand into multiple DEFINEs
    and thus must be "wrapped" in something to be spliced in correctly.
    If we define BEGIN in terms of LET, then the scope of FOO will have to
    be confined to the scope of the BEGIN.

    What should we do?  I vote that BEGIN indicate a compound expression,
    contrary to early Steele&Sussman, and that LET() be used for
    Algol-style blocks.

CASE expressions with single keys

    We will accept single keys in CASE expressions.  If ELSE is to be a
    single key in the last clause, however, it will have to be enclosed in
    parentheses to avoid being interpreted as "otherwise".

CALL/CC

    "CALL-WITH-CURRENT-CONTINUATION" is nonsense to the unititiated, too.
    I will support both, but feel like it's silly to have the long name.

    Must this be a procedure (e.g. a potential funarg) or can we treat it
    as a special form?

Transcendental functions

    What's the problem?  Just call them "optional" as a group.  What we've
    been arguing is whether I have "true Scheme" if I have some kind of
    representation for "real numbers" but don't support a certain set of
    functions.  This is irrational!! (sorry)

Generic LENGTH

    I strongly abhor Common LISP-style genericity.  As Will says, "generic"
    operations on numbers with multiple REPRESENTATIONS is one thing, but
    trying to be generic across different kinds of things is something
    else.

Case-sensitive symbols

    I feel very strongly that symbols, as processed by the reader, should
    NOT be case sensitive and that (EQ? 'a 'A) be true.  STRING->SYMBOL
    should preserve case, however, and (EQ? '|a| '|A|) should be false.

--  David Bartley       (Bartley @ TI-CSL)
-------


∂01-Dec-84  1049	RPG   	Kent Dybvig's Comments on Scheme 
 ∂30-Nov-84  2036	@MIT-MC:JINX@MIT-OZ 	Kent Dybvig's Comments on Scheme  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Nov 84  20:35:53 PST
Date: 30 Nov 1984  23:35 EST (Fri)
Message-ID: <JINX.12067849164.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: Kent Dybvig's Comments on Scheme
In-reply-to: Msg of 30 Nov 1984  12:47-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

	BEGIN should certainly not add another contour.  BEGIN is
equivalent to LET() if environments are not first class, but they are
in MIT Scheme.  An incremental definition to the environment where the
subexpressions of the BEGIN expression are evaluated would have
different effects depending on whether a new contour was created or
not.  I agree that BEGIN (for lack of a better name) should indicate a
compound expression and LET should be used for blocks. 
	
	Note that this is not contrary to all early Scheme papers
since in the Revised Report,

	(BLOCK X Y) = ((LAMBDA (A B) (B)) X (LAMBDA () Y)).

X is evaluated in the environment where the BEGIN
expression appears, and Y is evaluated in an environment where no
bindings have been added.  In a dialect without first-class
environments and without internal definitions, the environment where Y
is evaluated is the same as that where X is evaluated, thus no
contours have been added.

	I think that there are only two valid reasons for adding
special forms:

	- They provide a convenient syntax for something which
could be expressed only considerably more clumsily without them.
Example: COND (as compared to nested IFs).  These are usually macros
which expand into the clumsier form.

	- They provide an extension to the language which requires
special handling by the interpreter or compiler.  Their effect could
otherwise not be achieved.  Example: QUOTE.  These are the "TRUE"
special forms.

	I don't think that CALL-WITH-CURRENT-CONTINUATION falls in
either class, so there is no need to make it a special form.  Besides,
a portable program would not be able to rename it since we have not
specified a way for adding syntactic extensions.

	Allowing IF not to have an alternative sub-expression is
convenient because it is clear and eliminates the need for WHEN,
another special form.  I don't like the proliferation of special forms
and would object strongly to requiring another one for this purpose.
I can't see that there is a difference between WHEN and IF in terms of
compile-time checking.  IF with two subexpressions and IF with three
subexpressions can be treated as different beasts.

	I agree with the remaining three points.

- Bill Rozas (JINX@MIT-MC)

∂05-Dec-84  1353	RPG   	Re: Kent Dybvig's Comments on Scheme  
 ∂04-Dec-84  2015	@MIT-MC:HUDAK@YALE.ARPA 	Re: Kent Dybvig's Comments on Scheme    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 4 Dec 84  20:15:10 PST
Received: by YALE-BULLDOG.YALE.ARPA; 4 Dec 84 11:49:28 EST (Tue)
Message-Id: <8412041649.AA04845@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Tue, 4 Dec 84 11:37:43 EST
Subject: Re: Kent Dybvig's Comments on Scheme
Date: Tue, 4 Dec 84 11:37:46 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Bill Rozas <JINX%MIT-OZ@MIT-MC>
Cc: Scheme@MIT-MC, Hudak@YALE.ARPA
In-Reply-To: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>, 30 Nov 1984  23:35 EST (Fri)

Not having participated in the workshop, I've been hesistant about
making comments on the various issues flying by recently, but I couldn't
resist responding to Bill Roza's comments on special forms:

        I think that there are only two valid reasons for adding
    special forms:
    
            - They provide a convenient syntax for something which
    could be expressed only considerably more clumsily without them.
    Example: COND (as compared to nested IFs).  These are usually macros
    which expand into the clumsier form.
    
            - They provide an extension to the language which requires
    special handling by the interpreter or compiler.  Their effect could
    otherwise not be achieved.  Example: QUOTE.  These are the "TRUE"
    special forms.
    
I think there's one other reason, which in a sense subsumes the first:
*readability*.  In particular, with regard to IF having or not having
an alternative sub-expression, I find that when I'm reading code and
come across an IF expression, I look very hard to see if it has an
alternative branch.  If it doesn't, I look again to be sure I didn't
miss it.  I think this "convenient feature" degrades readability.
I agree with Bill Rozas that one shouldn't proliferate special forms,
but my reason is that they are typically complex, and their syntax
becomes hard to remember.  However you can't get much simpler than
WHEN and UNLESS.  Their use, in my opinion, greatly enhances
readability.

    - Paul Hudak (hudak@yale)

∂07-Dec-84  1341	RPG   	[willc: preliminary report of workshop]    
 ∂06-Dec-84  1909	KMP@MIT-MC 	[willc: preliminary report of workshop]    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 6 Dec 84  19:09:23 PST
Date: 6 December 1984 22:02-EST
From: Kent M Pitman <KMP @ MIT-MC>
Subject:  [willc: preliminary report of workshop]
To: willc%indiana.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-Reply-To: <8411120256.AA05811@iuvax.UUCP>

Ok, Will, I'm assuming things decided at the meeting are not cast in 
concrete. I certainly take issue with a number of the decisions.
In a few places, I also pick on your notation a bit when I think
its unclear. Thanks for taking the time to write up everything.
Here come the comments...

 * I dislike the description of "optional features". In particular,
   you say:

    Optional features may not be supported by every implementation,
    but those that do support a feature will use the same syntax and
    semantics for the feature.  Hence code that makes use of optional
    features will run on any implementation of Scheme that supplies
    the optional features.
    ....
    An implementation may extend the language in any way whatsoever,
    but code that makes use of extended features is not portable.

   These two paragraphs are in conflict and allow for lots of 
   inconsistency which I will identify at appropriate points later.
   The principle troubles, though, are:

   * Since a language can be extended in "any way whatsoever", 
     can such extensions be syntactically in conflict with optional
     language features? eg, if #\ is optional and my dialect doesn't
     use it, can I then define my own #\ as an extended part of the
     required subset?

   * In some cases, "required" language features can be redefined
     incompatibly by "optional" features. eg,
	(COND (FOO => X))
     has a well-defined semantics regardless of whether the optional
     "=>" feature of COND is present. However, that semantics is not
     the same in the two cases.

   The point I'm trying to make is that saying something is "optional" says
   little if anything unless you at least define that if anyone uses the
   syntax corresponding to the optionality in a dialect which doesn't support
   the feature, that he is in error. Put another way, extensions may not 
   invalidate optional features. On the other hand, if this were stipulated
   the list of "optional" features to which I objected would be quite lengthy.

 * I disagree with calling the string quote character "double quote".
   I prefer "doublequote". Since there is a character named "quote", the
   phrase "double quote" might designate '' instead of ".

 * In discussing what terminates tokens, you should say which of these
   characters (presumably all) are also single-character tokens. In
   particular, that "((A B)C)" is tokenized 
       {"(" "(A" " " "B" ")C" ")"}
    or {"(" "(" "A" " " "B" ")" "C" ")"}
   hangs in the balance. I'm sure no one disagrees, but if you're not going
   to be complete about these things, you are sort of wasting your time
   just trying to look formal about things.

 * I agree with reserving {, [, ], and }, but I would specify that they
   may be used as alphabetic according to syntactic escape conventions.


    Optionally, the following characters may be delimiters that
    terminate symbols:

 * What does it mean to say single quote, backquote and sharpsign
   may "optionally" terminate tokens?  It means expressions
   like (JOHN'S COAT) read differently in the different dialects. How
   is this distinct from saying "Optionally, the following characters
   may be delimiters that do not terminate symbols:"?  It only makes
   sense to say something is optional if it's going to mean that when
   it's present. I bet some dialects treat (JOHN'S COAT) as a two-list
   and others treat it as a three-list. Hence, any description of this
   relation between dialects can at best say: "The specification takes
   no stand on the issue of whether the following delimiters terminate
   symbols. Any use of expressions like (JOHN'S COAT) are to be considered
   non-portable."

 * I would personally prefer if vertical bar had been defined to be 
   alphabetic, but I am at least happy that it is "not specified" what
   its meaning is rather than that it is "optional".

 * I strongly oppose the idea of not specifying an escape char for 
   symbols. You say there is "widespread agreement that ``slashification''
   of characters within symbols is a relic that ought to be abandoned."
   I am not party to such agreement.

   I strongly oppose the idea of eliminating slashification. The Maclisp
   conventions of vertical bars made up for the absence of strings. With
   their passing, syntactic quoting of lots of chars is very rare, and
   in those few cases, I think slashing works fine. It also is a low-cost
   mechanism for the printer, since no lookahead is required. Also, it is
   uniform with respect to strings, which already use slash for special
   chars anyway. Finally, without slash, there would be no way to get 
   vbars into symbol names, since vbars cannot adequately quote themselves.
   On the other hand, slash can work fine in the absence of vbar. So if
   one thing is to go as a readsyntax quoter, it should be vbar.

 * Will-- Your meta-syntactic use of "..." in a description of what 
   the "." character does is very confusing.

 * Does anyone mind if (. A) is the same as A? It has a certain elegance
   to it if you think about it.
	(CONS 3 (CONS 2 (CONS 1 0)))	=> (3 . (2 . (1 . 0))) => (3 2 1 . 0)
		(CONS 2 (CONS 1 0))	=>      (2 . (1 . 0))  => (  2 1 . 0)
			(CONS 1 0)	=>	     (1 . 0)   => (    1 . 0)
			        0	=>	          0    => (      . 0)
   Just a thought.

 * I find #!true and #!false to be ugly and visually confusing
   with the popular convention of "!" designating something 
   destructive. It would make more sense for #! to be saved for
   something like #. in Common Lisp. I agree #<something>TRUE
   is reasonable. I'd have preferred #: for this.

 * What does it mean to say:
    "Optionally, binary numbers may be written using the #b notation.
     Optionally, octal numbers may be written using the #o notation.
     Optionally, decimal numbers may be written using the #d notation.
     Optionally, hexadecimal numbers may be written using the #x notation."
   Presumably this means that dialects not wanting #B, #O, etc. can 
   use these to mean other things.

 * What does it mean to say:
    "Optionally, special characters may be written using the #\
     notation.  If this feature is supported, then the Common Lisp
     names for special characters must be supported."
    Presumably this means that if I don't want to be able to write special
    characters, I can make #\ do something else. In fact, if I want to 
    use other names than those used by Common Lisp, I can just "not support"
    this feature and then "make any extension whatsoever" to my dialect
    such that #\ does something completely different, like understand
    a different set of character names.

 * Was anything decided about whether #!TRUE and #!FALSE would self-evaluate
   or whether they required quoting?

 * Was anything decided about whether numbers must self-evaluate or
   whether a dialect may require quoting?

 * Since "optionally, numbers may be written using decimal points and/or
   exponents", does this mean that numbers with decimal points are integers
   or floating? Does it mean that if I don't support the feature that
   I can take the alternate position?

 * I notice that the space of symbol names is highly constrained for
   the "required subset". A property, however, that should be required
   is that within any given dialect, every interned symbol (no matter what
   characters it contains) must have a printed representation which is
   read-invertable within that dialect. I suspect that all dialects 
   do this already anyway, but it should be a guaranteed property of the
   language since programmers will tend to depend on such things and should
   have a guaranteed semantics backing them up.

 * What does it mean to make NIL optionally evaluate to the empty list
   or optionally evaluate to false. What happens if I make it false and
   then try to run my code in another dialect where it's the empty list
   and where the two are not the same thing. The definition of optionality
   says that code written in the optional subset will run correctly in 
   another dialect supporting optional features. It doesn't seem to me
   like a good idea to optionally define a symbol as able to take on several
   values and then be able to write meaningful code.

 * It is specified that "the order of evaluation within an application 
   is not specified". I would prefer "combination" or "expression" to
   "application" as a matter of terminology to avoid confusion with the
   application that happens in the APPLY function, which doesn't involve
   evaluation at all.

 * I don't like the name LETREC; I preferred LABELS. Neither is very
   suggestive of anything; the latter is at least a real word.

 * Will-- I don't like the use of the term "mistake" throughout the report,
   at least without defining it formally. In my dialect, it connotes 
   an unintentional error and it seems to me that if the user 
   intentionally did the offending thing, it would not be a mistake.
   I would say "error" in its place, or define the term "mistake" 
   formally early on.

 * I disagree with the various forms that claim it to be a "mistake"
   to use certain return values, allowing some implementations to
   signal an error. I don't agree that such errors can ever be 
   detected at the language level; I would like a formal description
   of exactly when it is believed that such an error could be signalled.
   The forms in question are: IF, COND, SET!, DEFINE, DEFINE!, CASE,
   SET-CAR!, SET-CDR!, and VECTOR-SET!.

 * The semantics of (COND (X => Y)) is messy due to optionality as
   described earlier.

 * Will-- I would name the ... sequences in definitions of things 
   like LET, COND, etc which use multiple sequences. I realize you
   use them right to left, but that could be made more apparent.
   Perhaps ..foo.. instead of ...

 * I find the name SET! both ugly and redundant. The "!" convention
   as originally created by the T people identifies a destructive
   variant of an otherwise-non-side-effecting operation. So, for
   example, APPEND and APPEND!, etc. Logically, there could be a 
   CHANGE-CAR and CHANGE-CAR!, one of which was
     (LAMBDA (C V) (CONS V (CDR C)))
   and the other which was
     (LAMBDA (C V) (SET (CAR C) V) C)
   In any case, I strongly think that the primitive for assigment 
   should be SET and not SET!. In fact, since no one likes assignment
   anyway, I don't see any reason why anyone should object to just
   leaving this undefined in the standard. It would only discourage
   people from writing destructive code. But I would be very unhappy
   to see T change the name of SET to SET!. Similarly, I strongly
   dislike the name SET-CAR! and SET-CDR!.

 * The definition of DEFINE refers to the "top-level" definition of
   a variable. I don't believe it's established what "top-level" means, 
   so this definition is pretty muddy. Further, what is the implication
   of this definition upon doing (LAMBDA (X) (DEFINE X X))?

   I am very discouraged that the (DEFINE (fn . args) ...) syntax isn't
   required. This means that any portable code must be ugly, meaning
   no one is likely to ever write truly portable code, meaning this
   standard is a farce.

 * It is silly to require that there be at least one form in a (BEGIN).
   It is easy for macros to come up with situations where there are
   no forms to put there and as long as the macro's caller doesn't 
   depend on the value, it shouldn't matter. The return value of a
   BEGIN with no forms should just be undefined.

 * The fact that (LET* ...) cannot admit an optional name reveals an
   asymmetry which I find very distasteful. I suggest that named LET
   be left to implementors as an "arbitrary" extension not to be mentioned
   in any common subset.

 * I would prefer to have REC be called LABEL. Again, at least it's English.

 * I don't see any good reason to have DO not bind RETURN. Can someone
   elaborate on that?

 * The description of DEFINE inside LAMBDA is inconsistent with the
   earlier description of DEFINE as creating a toplevel definition.
   I think this should be a non-standard extension. I see no reason to
   dignify it with any "optional" status.

 * The term "top-level binding" is again completely vague in DEFINE!'s
   definition.

 * The definition of optionality specified that if an optional feature 
   was present, the dialect should prefer to call it by the "optional" 
   name. This is somewhat inconsistent with making SEQUENCE an optional
   synonym for BEGIN. Since it is not encouraged for use and is not going
   to exist in all dialects, is there any sense to including it here?

 * The entire section on datatypes is hopelessly muddled. About the only
   useful thing said is that anything which is a first class object must
   have unlimited extent.

 * In the sentence "There is an object which represents both false and
   the empty list", I cannot discern whether that means there may/must
   be one/two objects filling that description. Shouldn't we say,
   "False and the empty list must be represented as first class objects
   and that object {may,must} [not] be distinct." or some such.

 * Since datatypes are not declared to be disjoint, it isn't necessary
   to mention that characters may be represented as numbers, except perhaps
   as a footnote to remind the forgetful reader. Strings can be represented
   as numbers, too, the way things are written.

 * Was there really anyone who thought streams shouldn't be first class
   objects? Since datatypes aren't disjoint and such objects could be 
   indistinguishable from numbers or arrays or whatever, is there really
   a reason to care?

 * The unary procedure not should be defined to return "a true value if
   its argument is false and a false value if its argument is not false."
   ... rather than "if its argument is true." for the second part.

 * I suggest renaming CALL-WITH-CURRENT-CONTINUATION (or CALL/CC) to just
   CONTINUE. eg,	
		  (CONTINUE (LAMBDA (C) (IF (FOO) (F C) (G C))))
   Anyone else support this?

 * By the way, saying the escape procedure has unlimited extent doesn't say
   it can be called more than once. Does everyone agree to either stipulate
   that or not?

 * If "the unary predicate NUMBER? is true of numbers and false of
   everything else" and "the unary predicate INTEGER? is true of
   integers and false of everything else", I don't suppose this says
   much since types are not disjoint and so strings are not necessarily
   not numbers and need not necessarily cause INTEGER? or NUMBER? to
   return false. Certainly characters needn't yield false from NUMBER?
   or probably from INTEGER?. As such, these predicates are of limited
   value.

 * Of what point is it to make claims about what "almost all implementations"
   will do for real numbers? Either they're required to or they aren't.
   The rest belongs in some other document.

 * I don't agree that allowing generalization of +, -, *, and / to arbitrary
   arity is a good idea or even well-defined. eg, the proper generalization
   of - to arity 1 is (- 3) => 3, not (- 3) => -3. Hence, specifying that unary
   negation is optional is in conflict with specifying that - may be generalized.

 * Will-- The discussion of QUOTIENT/REMAINDER and of CONS/CAR/CDR should
   use the word "respectively" in the appropriate places. When I first read
   that QUOTIENT and REMAINDER return the quotient and remainder, I spent
   an unduly long time flipping back pages looking to see if you'd allowed
   multiple values before I realized that it was silly for both these functions
   to do the same thing or for that same thing to be what it had first looked
   to me like they're doing.

 * I don't see why MIN/MAX should be restricted from arity 0. They should
   just return the smallest and largest representable numbers. I guess as
   long as they aren't defined to signal an error in this case, individual
   dialects could be extended anyway.

 * It should be made explicit whether (= 1 1.0) is defined to work. Note that
   this may be tricky since even (= 1.0 1.0) won't necessarily work if the
   1.0's were computed rather than read and have different bit patterns that
   are too tiny to make a difference on output.

 * It is silly to specify that implementations may "optionally" support
   numbers that are non-integers. Why not just define that (NUMBER? x)
   doesn't imply (INTEGER? x). That definition wouldn't mean that 
   every number wasn't an integer, it would only mean that every number
   wasn't necessarily a number.

   Specifying that "almost all implementations" will support this option
   is again silly and might in pathological situations be misleading.

 * Is the definition of (TRUNCATE x) really correct? It looks like it must
   be screwed up on the negative side near 0. eg, (TRUNCATE -0.5) doesn't
   have the same sign as 0.5 does it? Or is there a negative 0?

 * The meaning of "interning" a symbol should be specified.

 * It should be stated explicitly that CAR and CDR of the empty list 
   is not defined.

 * What's this nonsense about pairs being maybe indistinguishable from
   vectors of length 2. Is there a good reason for that? It doesn't really
   matter since numbers haven't been defined as distinguishable from
   strings either, but it somehow offends my sense of aesthetics to see
   this note here. Is this due to some problem with Maclisp HUNK2's or
   something unrelated?

 * In "The following descriptions use the notion of a proper list.  The
       set of proper lists is the smallest set satisfying:
        the empty list is a proper list
        a pair x whose CDR is a proper list is a proper list,
            provided (MEMQ x (CDR x)) is false."
   I think MEMQ isn't the function that you want, but I find it amusing
   to see the language defined meta-circularly in this way (since MEMQ
   is almost certainly defined to terminate only on proper lists and may
   even want to type-check proper-list-ness).

 * Is the function LENGTH defined to err or to not return when given
   a circular list? What about an otherwise improper (ie, dotted) list?

 * The definition of APPEND is poor. It should be defined with NAMED-LAMBDA
   for safety in situations where APPEND gets redefined. Also, its text
   description is too windy.

 * I see no reason for APPEND! to be defined to possibly side-effect
   either arg. This may force lots of needless copying in order to write
   provably correct programs. I can't imagine a definition of APPEND!
   which would want to destructively modify its last argument.

 * All these definitions (APPEND, REVERSE, ...) are ugly due to the
   silly restrictive version of DEFINE. I certainly wouldn't want my
   students programming like that.

 * It should be stated in English what happens if LIST-REF and LIST-TAIL 
   fall off the end. I assume it follows from the definitions of CAR/CDR
   that such is a signallable error.

 * There should be MEMQ?, MEMV?, and MEMBER? to match MEMQ, MEMV, and
   MEMBER. This enhances garbage collection since if these functions 
   are only being used for truth value, you don't want to hold pointers
   to potentially large list structures. Also, it enhances debugging since
   if F is a function on booleans, (F (MEMQ X Y)) will receive true/false 
   rather than a list or false. Ditto for ASSQ?, ASSV?, and ASSOC?.

 * You specify no order of evaluation for MAPCAR. I think you mean no
   order of "application".

 * I dislike the asymmetry between MAPCAR and MAPC. 
     MAPC has no defined return value, MAPCAR does.
     MAPC has defined order of application, MAPCAR does not.
   In short, they have nothing really in common other than they type
   of their args. I think they should not be named so similarly.

 * I oppose the names MAPCAR and MAPC. 
   T calls these MAP and WALK, respectively.
   The generic form of MAPCAR, which is the only thing for which
   arbitrary order of application would make sense (since lists are
   only sequentially accessible anyway), has no business being called
   MAPCAR.

 * With respect to the questions about VECTOR->LIST, I think the
   right thing to say is that the conses it returns are mutable,
   not that the result is necessarily a "new object", since if the
   result is the empty list (eg, from an empty vector), I wouldn't
   want the implication to be that 
      (NOT (EQ (VECTOR->LIST #()) (VECTOR->LIST #())))
   since it follows from that that more than one false value must
   (rather than "may") be possible.

 * What happens if VECTOR-REF is out of range?

 * VECTOR-SET! is ugly. It should at least be called SET-VECTOR-REF!
   for symmetry with the other SET- things. Personally, I hate the
   ! and would strongly prefer just SET-VECTOR-REF.

 * The relation between OBJECT-HASH and the GC should be specified.
   Do things get GC'd if no other pointers exist to them? Also, it
   might help to distinguish this kind of "hash" from the number that
   comes from SXHASH in Maclisp. It took me a second to realize you
   weren't talking about that.

------- End undelivered message -------

------- End undelivered message -------

∂07-Dec-84  1342	RPG   	Slashification    
 ∂07-Dec-84  1327	JAR@MIT-MC 	Slashification    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 7 Dec 84  13:27:00 PST
Date: 7 December 1984 16:26-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  Slashification
To: KMP @ MIT-MC
cc: SCHEME @ MIT-MC
In-reply-to: Msg of 6 Dec 1984 22:02-EST from Kent M Pitman <KMP>

I think I was the one who suggested that there be neither slashification
nor vertical barring.  If you tell the T printer not to use either \ or
| and it comes across a symbol which requires quoting anyhow, it prints
#[Symbol "foo"].  (If you have \ but not |, as in T, you need to have a
way to print the null symbol anyhow; it really does come out as #[Symbol
""] - try it.)  If print tables exist or if STRING->SYMBOL accepts any
string whatsoever, then it is necessary to have some way for unusual
symbols to read and print, but there's not really any need to wire down
a special character for the purpose, because e.g. some # syntax could be
used.

Some people wanted to throw away \ in favor of just | ; people didn't
agree when I suggested going with \ but not | ; so we just decided that
the need was unimportant enough that neither syntax was required.  I'm
not convinced that there needs to be a defined, portable way to print
unusual symbols, although maybe you could talk me into such a position.

Jonathan

∂09-Dec-84  1252	RPG   	MIN/MAX, DO/RETURN
 ∂08-Dec-84  1556	KMP@MIT-MC 	MIN/MAX, DO/RETURN
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 8 Dec 84  15:56:47 PST
Date: 8 December 1984 18:55-EST
From: Kent M Pitman <KMP @ MIT-MC>
Subject:  MIN/MAX, DO/RETURN
To: SCHEME @ MIT-MC
References: Msg of 6 Dec 1984 22:02-EST from Kent M Pitman <KMP@MIT-MC.ARPA>

Jonathan Rees had a good points about a couple of my earlier remarks...

* Making MIN/MAX return smallest/largest representable number would
  be infeasible in implementions with bigfloats or bignums. I should
  have thought of that. (I must have been thinking too hard about 
  the flonum case; sorry.) I'll withdraw that suggestion.

* Making DO bind RETURN would have been a bad idea since it would "wire"
  the name RETURN. I withdraw my disparaging remarks about its not binding
  that name.

-kmp

∂09-Dec-84  1304	RPG   	Re: critique of preliminary report    
 ∂09-Dec-84  1142	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Re: critique of preliminary report
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Dec 84  11:42:25 PST
Received: from indiana by csnet-relay.csnet id a022287; 9 Dec 84 14:34 EST
Received: by iuvax.UUCP (4.12/4.7)
	id AA06716; Sat, 8 Dec 84 22:50:32 est
Date: Sat, 8 Dec 84 22:50:32 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
To: KMP@mit-mc.ARPA
Subject: Re: critique of preliminary report
Cc: scheme@mit-mc.ARPA

I am posting this in response to Kent Pitman's excellent critique
of the preliminary report on the October workshop.


ERRORS AND OVERSIGHTS

I should have said:

Numbers, strings, characters, and #!TRUE and #!FALSE are
self-evaluating, which means they need not be quoted. Symbols and
pairs are not self-evaluating.  It is not specified whether other
things are self-evaluating.

The semantics of (BEGIN) is not specified.

TRUNCATE could be defined by

    (DEFINE TRUNCATE
      (LAMBDA (X)
        (IF (NEGATIVE? X)
	    (- 0 (FLOOR (ABS X)))
	    (FLOOR X))))

VECTOR-REF takes a vector v and an nonnegative integer n such
that n < (VECTOR-LENGTH v) and returns ... .

----------------------------------------------------------------

WHAT DOES "OPTIONAL" MEAN?

The intent of the workshop was that extensions must not conflict
with optional features, and I should have said so.  In fact some
features were made optional in order to prevent dialects from
using certain syntaxes for other purposes.  It follows that #b,
#o, #d, #x, #\, and so on can't be used for any purpose other
than to support the optional feature.

I agree that the "optional" stuff about NIL and T is ridiculous.
What I should have said instead is that implementations that want
to treat NIL and T as constants can do so.  In effect this is a
warning against using NIL and T to name variables.  Note that
(FOO . NIL) cannot read the same as (FOO) no matter what.

I didn't mean to say that "optional" names or features are to be
preferred to essential names or features, and I don't think I did.

----------------------------------------------------------------

POOR WRITING IN THE PRELIMINARY REPORT

I agree with Kent Pitman's points regarding the use of "...",
"mistake", "respectively", and "double quote".

I agree that the set of single character tokens needs to be
better defined.  I would like to include appendixes in the final
report with more rigorous descriptions of the lexical syntax, the
context-free syntax, and the denotational semantics of Scheme.

How about "The order of evaluation within a procedure call is not
specified"?  That isn't quite true, of course -- normal order
evaluation is prohibited.

I should have said that some single object represents both false
and the empty list.  There may be other objects representing
false.  Might there be other objects representing the empty list?
(I hope not.)

I agree that it would be better to have said that (NUMBER? x)
doesn't imply (INTEGER? x).

I hope everyone noticed that it is an error to take the CAR or
CDR of the empty list.

The definition of a proper list in the preliminary manual was a
joke.  The notion of a proper list has to do with finiteness,
which is not first order definable.

----------------------------------------------------------------

LEXICAL MATTERS

It is not specified whether single quote, backquote, sharp sign,
and vertical bar are delimiters that terminate symbols.  The
status of these characters would be decided by a general rule
that emerged during discussion at the workshop, but not everyone
agreed to the general rule.  The general rule is:  Special
characters that come in pairs (left and right parenthesis, left
and right bracket, left and right curly brace, doublequote)
should be delimiters while other special characters (period and
so on) should be preceded by a space if they are to be used in
their special sense.  Semicolon isn't really an exception to the
pattern because the end of line would be a delimiter anyway.
Whether vertical bar should be a delimiter according to the rule
depends on whether vertical bar is a special character that comes
in pairs, which is not specified.  According to the rule single
quote, backquote, and sharp sign should not be delimiters.

> * I agree with reserving {, [, ], and }, but I would specify that they
>   may be used as alphabetic according to syntactic escape conventions.

I don't understand "...according to syntactic escape conventions".

I have yet to hear of a good use for slashification of symbols.
If there is no compelling need for a feature, we should leave it
out.  The workshop allowed slashification but did not encourage
it.

> * I notice that the space of symbol names is highly constrained for
>   the "required subset". A property, however, that should be required
>   is that within any given dialect, every interned symbol (no matter what
>   characters it contains) must have a printed representation which is
>   read-invertable within that dialect. I suspect that all dialects 
>   do this already anyway, but it should be a guaranteed property of the
>   language since programmers will tend to depend on such things and should
>   have a guaranteed semantics backing them up.

We probably ought to require something along these lines, but the
property you desire is too strong.  It is enough that every
symbol read by the reader be printed in a form that will read
back in as the same symbol.  Other symbols are too random to
worry about.  In fact, I would be satisfied if only the required
set of symbol names have the property you desire.  For what it's
worth, Franz Lisp does not have the property, but I doubt that
its lack is a significant cause of dissatisfaction with Franz
Lisp.

----------------------------------------------------------------

SPECIAL FORMS

LETREC vs LABELS, REC vs LABEL, and SET vs SET! are matters of
taste that needed to be decided one way or the other, and were.
History plays a significant role in decisions such as these.  The
first two matters had history on both sides, but the history of
SET in traditional Lisp counts against it.

In some cases the IF, COND, and CASE special forms return
unspecified values.  The SET!, DEFINE, and DEFINE! special forms,
and the SET-CAR!, SET-CDR!, and VECTOR-SET! procedures, always
return unspecified values.  Except for the result of the DEFINE
form, I wrote that it is a "mistake" to use these undefined
values, and except for the results of the DEFINE and DEFINE!
forms I wrote that implementations could signal an error if the
values that were returned were "used".  What I wrote is faithful
to the workshop's decisions, but I can be accused of deviating in
the cases of DEFINE and DEFINE! .

Kent is right to question what we meant by "using" a value.  The
answer is that we don't know.  Obviously an implementation could
return a strange value that would cause an error to be signalled
if an attempt were ever made to take its CAR or its successor; an
implementation could also arrange for an error to be signalled if
the value were ever an operand to EQ? or CONS; and there are no
doubt other things that an implementation could do as well.  I
will not offer a formal description of the circumstances under
which an error could be signalled, because I want to leave room
for implementations to experiment with different approaches.

A DEFINE form is at "top level" iff it it not nested within any
other form.  This definition clearly establishes circumstances
that do not count as top level, but it does not establish any
circumstances that do count as top level.  I think each
implementation will have to specify circumstances under which a
DEFINE form has the described semantics, and those circumstances
would then count as top level for that implementation.

The Abelson and Sussman book uses DEFINE inside LAMBDA as
syntactic sugar.  Scheme's future is tied to the success of that
book, so the sugar was dignified with "optional" status.  The
optional status of the sugar required that ordinary DEFINE be
restricted to "top level".

The (DEFINE (fn . args) . body) sugar was dignified with
"optional" status for the same reason.  Kent has acquired a taste
for this sugar, but I consider it a violation of orthogonality
that is doubly pernicious:  (1) it discourages programmers from
thinking of procedures as objects distinct from their names; (2)
it discourages programmers from using procedures with local
state.

I agree that the optional status of named LET should imply an
optional status for named LET*, or else both named LET and named
LET* should be left out altogether.  By the way, David Bartley
asks whether the body of a named let is within the scope of the
name.  The Revised Report has the body within the scope of the
name.  Does anyone want to argue that the body should be outside
the scope of the name?

When it was asked if DO should bind RETURN, someone said "Of
course not!", and that was the end of the discussion.  If DO were
to bind RETURN I believe that DO would be the only construct in
even the optional language to bind an identifier that does not
appear explicitly in the code, and I see no reason to condone
that kind of anomaly.

----------------------------------------------------------------

DATATYPES

I was disappointed that we were unable to agree that any
datatypes were disjoint.  The fact that the workshop participants
insisted on a special note to the effect that characters need not
be a distinguishable data type leads me to believe that despite
their votes most participants assumed that other data types were
distinguishable.  In the final report I intend to recommend that
at the very least numbers, symbols, and pairs should be disjoint;
does anyone object?

Even without disjointness of data types, the NUMBER? and INTEGER?
predicates are useful because they define the domains of other
procedures.  Thus if all strings are numbers then it must be
possible to subtract strings.

The nonsense to the effect that pairs might be indistinguishable
from vectors of length 2 is to remind folks not to assume that
pairs and vectors are disjoint.  I agree that the note is out of
place and ugly.

I expect streams will be a Scheme data type, but as Kent points
out they might overlap with (say) numbers.  Nonetheless the
STREAM? predicate will be useful because anything of which the
STREAM? predicate is true will have to support the operations on
streams.

----------------------------------------------------------------

PROCEDURES

I think it went without saying that escape procedures can be
called more than once.  We didn't feel any need to say that the
addition procedure could be called more than once, either.

The generalizations of +, -, *, and / to arbitrary arity must
follow Common Lisp, so the ambiguity is not great.  There is some
ambiguity, however, because Common Lisp has all sorts of rules
about integers, rationals, floats, and complexes that don't apply
to Scheme.

MIN and MAX are restricted from arity 0 because some
implementations don't have a smallest or largest representable
number.

Implementations should not be allowed to signal an error on
something like (=? 1 1.0).  I don't think we should specify that
the result is true because you might want to implement a Scheme
in which "approximations" are a subtype of the numbers, in which
1.0 is read in as an approximation, and in which all equality
comparisons involving approximate numbers return false.

(If you haven't caught on by now, I'm perfectly comfortable with
the fact that Scheme is far less tightly specified than Common
Lisp.  I believe Scheme can continue to represent the future of
Lisp only by being open to experimentation.)

I would rather not talk about "interning" a symbol, because
there is no need to talk about it when all symbols are interned.
I have to use words like "interned" to talk about implementations
in which not all symbols are interned, but for definitions I
would like to refer people to manuals for traditional Lisps.

LENGTH is defined on proper lists, and its action on anything
else is not specified.

I can't imagine a definition of APPEND! that would want to mutate
its last argument either.  Shall we say it doesn't?

Kent's suggestions for MEMQ?, MEMV?, MEMBER?, ASSQ?, ASSV?, and
ASSOC? are interesting.  Several people at the workshop, notably
Hal Abelson, expressed the belief that we ought to reconsider the
entire MEMBER/ASSOC complex of procedures.

MAPCAR and MAPC have their historical names for historical
reasons, and I would not be averse to renaming them eventually.
If MAPCAR is defined as follows in an implementation that
evaluates right to left, then the list of results is constructed
from right to left:

	(DEFINE MAPCAR
	  (LAMBDA (F L)
	    (IF (NULL? L)
	        '()
		(CONS (F (CAR L)) (MAPCAR F (CDR L))))))

I agree with Kent that the result of VECTOR->LIST cannot
reasonably be guaranteed to be a new object.

VECTOR-SET!, SET-CAR!, and SET-CDR! seem inconsistent to me too.
I think we should offer a prize for the best rationalization of
these names.

I think garbage collection should be treated as an issue of
performance rather than as an issue of semantics.

				Peace, William Clinger


∂09-Dec-84  1307	RPG   	apology to Franz Lisp  
 ∂09-Dec-84  1145	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	apology to Franz Lisp   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Dec 84  11:44:54 PST
Received: from indiana by csnet-relay.csnet id ab22287; 9 Dec 84 14:36 EST
Received: by iuvax.UUCP (4.12/4.7)
	id AA01074; Sun, 9 Dec 84 11:11:13 est
Date: Sun, 9 Dec 84 11:11:13 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
To: scheme@mit-mc.ARPA
Subject: apology to Franz Lisp

I apologize to Franz Lisp for claiming that not every interned symbol in
Franz has a printed representation that reads back in as the same symbol.
An example confused me but not Franz Lisp.

				Peace, William Clinger


∂10-Dec-84  1123	RPG   	Scheme conference report    
 ∂09-Dec-84  1648	@MIT-MC:ANDY@SU-SCORE.ARPA 	Scheme conference report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Dec 84  16:48:24 PST
Date: Sun 9 Dec 84 16:45:14-PST
From: Andy Freeman <ANDY@SU-SCORE.ARPA>
Subject: Scheme conference report
To: scheme@MIT-MC.ARPA

Will the final report on the scheme conference say anything about
macros?  There are substantial issues to be resolved/understood,
especially in scoping and expansion, but can a "least common
denominator" solution be released in the interim?  How about a syntax
for defining top-level macros?  That can be useful even if everything
else is undefined or optional.

Speaking of top-level solutions, why was ",." left out of the
backquote syntax?  (It's like ",@", except that the value of the
following form may be destructively spliced into the result.  ",@", as
you recall, non-destructively splices the value of the following form
into the result.)  If deeper levels of nesting are going to be
optional, the report has to define what happens.

By the way, unless Scheme is going to define a character set, EOF
isn't necessarily a character.  Neither is end-of-line.

Are all symbols interned or not?  (Interning isn't necessary to print
code and be able to read it back in later.)

Still, most of these are minor issues.  What the final report really
needs is a discussion of the decisions.  Some things do not need
explanation (except to historians), like the names lambda and ', but,
for instance, why are true and false self-evaluating?  In many cases
the decision itself is unimportant, but the issues are.

The report would also be improved by explicit mention of controversial
issues.  So there's no decision; the reasons are still important.

-andy

ps - Why is argument evaluation order unspecified?  That was a mistake
in Pascal, but then AND/OR/etc. have a defined order in Scheme.  Then
again, so many standard forms have a right-left defined order that
consistency would suggest that user procedures should also.

Is the closure position an argument?
-------

∂10-Dec-84  1137	RPG   	Scheme conference report    
 ∂09-Dec-84  1648	@MIT-MC:ANDY@SU-SCORE.ARPA 	Scheme conference report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Dec 84  16:48:24 PST
Date: Sun 9 Dec 84 16:45:14-PST
From: Andy Freeman <ANDY@SU-SCORE.ARPA>
Subject: Scheme conference report
To: scheme@MIT-MC.ARPA

Will the final report on the scheme conference say anything about
macros?  There are substantial issues to be resolved/understood,
especially in scoping and expansion, but can a "least common
denominator" solution be released in the interim?  How about a syntax
for defining top-level macros?  That can be useful even if everything
else is undefined or optional.

Speaking of top-level solutions, why was ",." left out of the
backquote syntax?  (It's like ",@", except that the value of the
following form may be destructively spliced into the result.  ",@", as
you recall, non-destructively splices the value of the following form
into the result.)  If deeper levels of nesting are going to be
optional, the report has to define what happens.

By the way, unless Scheme is going to define a character set, EOF
isn't necessarily a character.  Neither is end-of-line.

Are all symbols interned or not?  (Interning isn't necessary to print
code and be able to read it back in later.)

Still, most of these are minor issues.  What the final report really
needs is a discussion of the decisions.  Some things do not need
explanation (except to historians), like the names lambda and ', but,
for instance, why are true and false self-evaluating?  In many cases
the decision itself is unimportant, but the issues are.

The report would also be improved by explicit mention of controversial
issues.  So there's no decision; the reasons are still important.

-andy

ps - Why is argument evaluation order unspecified?  That was a mistake
in Pascal, but then AND/OR/etc. have a defined order in Scheme.  Then
again, so many standard forms have a right-left defined order that
consistency would suggest that user procedures should also.

Is the closure position an argument?
-------

∂10-Dec-84  1142	RPG   	Scheme conference report    
 ∂10-Dec-84  0930	@MIT-MC:JINX@MIT-OZ 	Scheme conference report
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  09:30:02 PST
Date: 10 Dec 1984  12:24 EST (Mon)
Message-ID: <JINX.12070348515.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Andy Freeman <ANDY@SU-SCORE.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: Scheme conference report

	I would like to clarify (hopefully) a few points with respect
to the evaluation of combinations:

	The operator position is a "distinguished" argument.  In my
opinion it is the only position for which the evaluation order might
be relevant.  If reflective procedures are present in an
implementation, then the operator position must be evaluated before
any operand expressions.  Since in the common subset there is no
provision for reflective procedures, there is no need to specify any
particular order with respect to the operator.

	In Will's last message there was a statement to the effect
that normal order evaluation was prohibited.  I find this rather
surprising.  One of Guy Steele's Rabbit compiler main points was that
normal order beta-subtitution could be used very successfully to
optimize Scheme code.  In the absence of side-effects, and if the
programs terminate when using applicative order, there is no way to
determine whether normal or applicative order is used.  A compiler can
use this profitably to postpone evaluation.  A think that a more
appropriate statement is that portable programs should not depend on
the evaluation strategy used, ie. they should work in applicative
order, but different implementations may want to use different
strategies.

	The order of argument evaluation was left unspecified for
various reasons:

	- The order of argument evaluation is only relevant in the
presence of side-effects in some of the argument expressions.  Scheme
is predominantly an applicative language (contrast with Pascal), and
good style requires that arguments to procedures (operands of
combinations) be side-effect free.  By not specifying the order, it
was felt that code with such side-effects would be discouraged since
its effect would not be predictable.

	- An optimizing compiler can do a better job if it has freedom
over the order in which it can execute expressions.  Leaving the order
unspecified potentially allows a clever compiler to choose the optimal
order for each combination.  Note that the meaning of a program can
only be changed by reordering if the argument expressions contain
side-effects.  But this code could not be guaranteed to work in other
implementations with different default order for argument evaluation.

	- Leaving the order of argument evaluation unspecified allows
a parallel implementation to evaluate in parallel.  Note again that
the only programs whose semantics are not clear (and are therefore not
predictable) are those with side-effects in the operands of a
combination.

	A marginally related issue is the issue of macros.  In Scheme
there is not so much of a need to provide a macro facility as in other
dialects of Lisp.  Macros are needed only to provide "nicer", more
readable syntax.  In other dialects they are needed to extend the
langauge since there is no way of encapsulating an expression and an
environment.  Freezing ("thunkifying", wrapping in a lambda
expression) an argument encapsulates a context and an expression in a
procedure which can then be invoked at will by the operator procedure.
While syntactically clumsy, it is conceptually very elegant.  Note
that an optimizing compiler (Rabbit, for example) can eliminate most
or all of the overhead of freezing and thawing.

∂12-Dec-84  1711	RPG   	Re:  Scheme conference report    
 ∂12-Dec-84  1601	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  Scheme conference report 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Dec 84  16:01:03 PST
Received: from unc by csnet-relay.csnet id aa04450; 12 Dec 84 15:04 EST
Received: by unc (4.12/4.7) id AA29958; Tue, 11 Dec 84 00:04:48 est
Date: Tue, 11 Dec 84 00:04:48 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8412110504.AA29958@unc>
To: ANDY@su-score.ARPA, scheme@mit-mc.ARPA
Subject: Re:  Scheme conference report

Relative order of evaluation of the expressions in a combination is
not specified for at least two reasons:

    1)	It is poor coding style to depend on order of evaluation.  If
	there is an ordering constraint it should be made explicit
	by using "let" or some such.

    2)	It is a severe constraint on the implementation for the language
	to specify an evaluation order.  What is easy for one machine
	model or architecture may be difficult for another.

Note that Pascal and Scheme are not alone; neither C nor Common Lisp
specify the order of evaluation.

	Kent Dybvig

∂12-Dec-84  1847	RPG  
 ∂12-Dec-84  1837	KMP@MIT-MC
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Dec 84  18:37:11 PST
Date: 12 December 1984 21:37-EST
From: Kent M Pitman <KMP @ MIT-MC>
To: dyb%unc.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC

Actually, Common Lisp does specify the order of evaluation as left to right.
It's tricky to find the passages in the CL manual which assure this, but
they are there if you look hard enough. The issue came up recently in the
Common Lisp discussion group and subsided after various obscure but recently
conclusive passages were cited.

Anyway, I agree it is reasonable to leave the order unspecified. It may be
computationally infeasible for the compiler to determine when order of
evaluation matters in many situations where "better code" would be available
if such a determination could be made.

∂15-Dec-84  2257	RPG   	Scheme bibliography    
 ∂15-Dec-84  1655	@MIT-MC:CPH@MIT-OZ 	Scheme bibliography 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Dec 84  16:55:16 PST
Date: Sat, 15 Dec 1984  19:53 EST
Message-ID: <CPH.12071740976.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell)
Cc:   T-Discussion%MIT-OZ@MIT-MC.ARPA, Scheme@MIT-MC
Subject: Scheme bibliography
In-reply-to: Msg of 14 Dec 1984  13:44-EST
      Fri 14 Dec 84 09:26:47 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell%UUCP at YALE.ARPA (John D. Ramsdell)

I believe that this is a complete list of the early Scheme papers:

Steele, Guy Lewis, Jr., and Gerald Jay Sussman.  1975.  Scheme: An
interpreter for the extended lambda calculus.  Memo 349, MIT
Artificial Intelligence Laboratory.

Steele, Guy Lewis, Jr., and Gerald Jay Sussman.  1976.  Lambda: The
ultimate imperative.  Memo 353, MIT Artificial Intelligence
Laboratory.

Steele, Guy Lewis, Jr.  1976.  Lambda: The ultimate declarative.  Memo
379, MIT Artificial Intelligence Laboratory.

Steele, Guy Lewis, Jr.  1977.  Debunking the "expensive procedure
call" myth.  In Proceedings of the National Conference of the ACM, pp.
153-62.

Steele, Guy Lewis, Jr., and Gerald Jay Sussman. January 1978.  The
revised report on Scheme: A dialect of Lisp.  Memo 452, MIT Artificial
Intelligence Laboratory.

Sussman, Gerald Jay, and Guy Lewis Steele, Jr.  May 1978.  The art of
the interpreter or, The modularity complex.  Memo 452, MIT Artificial
Intelligence Laboratory.

Steele, Guy Lewis, Jr.  May 1978.  Rabbit: A compiler for Scheme.
Technical report 474, MIT Artificial Intelligence Laboratory.

∂16-Dec-84  2313	RPG   	continuation terminology    
 ∂16-Dec-84  2039	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	continuation terminology  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 16 Dec 84  20:39:11 PST
Received: from indiana by csnet-relay.csnet id a001364; 16 Dec 84 23:35 EST
Received: by iuvax.UUCP (4.12/4.7)
	id AA04292; Sun, 16 Dec 84 17:27:40 est
Date: Sun, 16 Dec 84 17:27:40 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
To: scheme@mit-mc.ARPA
Subject: continuation terminology

We object strongly to the use of the term "escape procedure".  The word
"escape" is far to limiting to describe continuations, which are good for so
much more.  Also, the term "escape procedure" is strongly associated with the
limited facility by that name provided by most Lisp systems (which isn't good
for much besides "escaping").  If we adopt the old Lisp name, many will
assume that continuations aren't good for anything more than Lisp escape
procedures, and will miss what we feel is one of the most important
distinguishing features of Scheme.

We find the term "continuation" to be quit satisfactory in most contexts, and
it agrees with the name "call-with-current-continuation".  However, we
recognize that in the context of denotational semantics or implementation
discussions, there is possibility of confusing continuations as first-class
programming objects and their semantic or implementation counterparts.  Thus
additional terminology is desirable when such distinctions must be made, and
to standardize such terminology it should probably be used in the Revised
Revised Report.  We suggest the term "continuation object" for this purpose,
though it is not wonderful and we welcome other suggestions.

-- Chris Haynes
   Dan Friedman
   Eugene Kohlbecker


∂17-Dec-84  1524	RPG   	continuation terminology    
 ∂17-Dec-84  1523	JAR@MIT-MC 	continuation terminology    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Dec 84  15:23:41 PST
Date: 17 December 1984 18:23-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  continuation terminology
To: cth%indiana.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of Sun 16 Dec 84 17:27:40 est from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    Date: Sun, 16 Dec 84 17:27:40 est
    From: Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    We object strongly to the use of the term "escape procedure"...

My only objection to the terms "continuation" and "continuation object"
is that the presence of fluids and/or UNWIND-PROTECT mean that the thing
created by the user-visible CATCH or CONTINUE or CALL-... or whatever is
more than just a continuation, since it implicitly includes a reference
to the dynamic state.  There is a low-level thing which really does give
you a continuation, but I expect that the mechanism which does the right
thing with fluids would be the normal one used by users.

I don't have any new alternative term to propose, however.

Of course, we decided not to decide whether or not the essential
scheme's continuation procuration combinator dealt properly with fluids,
since essential scheme doesn't deal with fluids at all.  It seems to me
that any fluid mechanism whatsoever must distinguish between
continuations and continuation+state things.  As things are, my guess is
that it would be up to the implementor which of these two things the
essential dialect's CALL-... gives you.  (This might be the wrong thing,
but I won't argue that position here - this message is already too long.)

(By the way, no Lisp has never had escape procedures per se; the usual
CATCH/THROW mechanism doesn't introduce a new kind of object.  I'm not
convinced that the term "escape procedure" is as broken as you think it
is, or that it necessarily has such strong connotations.  But I'm not
partial to the term.)

∂18-Dec-84  2009	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Common Lisp order of evaluation    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Dec 84  20:09:07 PST
Received: from unc by csnet-relay.csnet id ac00691; 18 Dec 84 14:57 EST
Received: by unc (4.12/4.7) id AA12698; Fri, 14 Dec 84 10:29:23 est
Date: Fri, 14 Dec 84 10:29:23 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8412141529.AA12698@unc>
To: KMP@mit-mc.ARPA, SCHEME@mit-mc.ARPA
Subject: Common Lisp order of evaluation

If you have found passages which indicate a specific order of
evaluation, I'd like to know about it.  All that I have found
in scouring the manual several times over, in several different
versions over the years, is that arguments are 'processed' in
left-right order *once they reach the caller*.  Regardless of
any intentions on the designer's part, or any decisions of
discussion groups, any feature of the language that is not
spelled out is subject to interpretation.  There is certainly
nowhere in the manual that states that arguments are evaluated
in left-right order.

∂19-Dec-84  0850	@MIT-MC:rhh@MIT-VAX 	Re:  Common Lisp order of evaluation   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Dec 84  08:49:55 PST
Received: by mit-vax.Mit-chaos.Arpa (4.12/4.8) id AA25785; Wed, 19 Dec 84 11:40:26 est
Date: Wed, 19 Dec 84 11:40:26 est
From: Bert Halstead <rhh@mit-vax>
To: KMP@mit-mc.ARPA, SCHEME@mit-mc.ARPA, dyb%unc.csnet@csnet-relay.arpa
Subject: Re:  Common Lisp order of evaluation

The following passages out of the Common Lisp book may be relevant:

"setf carefully arranges to preserve the usual left-to-right order
in which the various subforms are evaluated."  (p. 97)

"Macros that manipulate generalized variables must guarantee the
'obvious' semantics:  subforms of generalized-variable references
are evaluated exactly as many times as they appear in the source
program, and they are evaluated in the same order as they appear
in the source program."  (p. 99)
							-Bert

∂19-Dec-84  0912	@MIT-MC:CPH@MIT-OZ 	Common Lisp order of evaluation    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Dec 84  09:12:05 PST
Date: Wed, 19 Dec 1984  12:12 EST
Message-ID: <CPH.12072705547.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Scheme@MIT-MC
Subject: Common Lisp order of evaluation
In-reply-to: Msg of 19 Dec 1984  11:40-EST from Bert Halstead <rhh at mit-vax>

Come on, folks...  This really isn't a great place to argue about what
order Common Lisp evaluates its arguments.  I for one don't care and
would rather not know.

∂23-Dec-84  0901	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	length vs. list-length   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Dec 84  09:00:57 PST
Received: from unc by csnet-relay.csnet id ag24249; 23 Dec 84 11:49 EST
Received: by unc (4.12/4.7) id AA29885; Sun, 23 Dec 84 01:06:25 est
Date: Sun, 23 Dec 84 01:06:25 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8412230606.AA29885@unc>
To: scheme@mit-mc.ARPA
Subject: length vs. list-length

My primary concern about the length function seems to have been
lost in the ensuing discussions.  I do not insist that Scheme
have a generic length function.  I do insist that the naming
convention for such functions be consistent.

Doesn't this look a little odd?
    (define generic-length
	(lambda (x)
	    (cond ((string? x) (string-length x))
		  ((vector? x) (vector-length x))
		  ((list? x) (length x)))))

I like this much better:
    (define generic-length
	(lambda (x)
	    (cond ((string? x) (string-length x))
		  ((vector? x) (vector-length x))
		  ((list? x) (list-length x)))))

We have list-ref, vector-ref and string-ref.  Why should we not
have list-length rather than length?  While we're at it, why
not have list-append rather than append?  Any functions that makes
sense for strings, lists, and vectors should be named with
the appropriate type-name prefix.  (Even though the language
doesn't specify a reverse function for vectors or strings
and since such functions would be reasonable, the reverse
function for lists should be named list-reverse.)


∂23-Dec-84  2330	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	list-length
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Dec 84  23:30:17 PST
Received: from brandeis by csnet-relay.csnet id a026028; 24 Dec 84 2:15 EST
Received: by brandeis.ARPA (4.12/)
	id AA06312; Sun, 23 Dec 84 22:31:44 est
Date: 23 Dec 1984 22:30-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: list-length
To: scheme@mit-mc.ARPA
Cc: dyb%unc.csnet@csnet-relay.arpa
Message-Id: <472707016/mw@brandeis>

I vote for list-length over length, too.  I think we just went over
that one a little too rapidly at the meeting.

-- Mitch Wand


∂24-Dec-84  1350	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	list-length
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Dec 84  13:50:48 PST
Received: from brandeis by csnet-relay.csnet id a026028; 24 Dec 84 2:15 EST
Received: by brandeis.ARPA (4.12/)
	id AA06312; Sun, 23 Dec 84 22:31:44 est
Date: 23 Dec 1984 22:30-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: list-length
To: scheme@mit-mc.ARPA
Cc: dyb%unc.csnet@csnet-relay.arpa
Message-Id: <472707016/mw@brandeis>

I vote for list-length over length, too.  I think we just went over
that one a little too rapidly at the meeting.

-- Mitch Wand


∂28-Dec-84  1428	JAR@MIT-MC 	list-length  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Dec 84  14:28:26 PST
Date: 28 December 1984 17:29-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  list-length
To: SCHEME @ MIT-MC
In-reply-to: Msg of 23 Dec 1984 22:30-EST from mw%brandeis.csnet at csnet-relay.arpa

LIST-APPEND, LIST-REVERSE, LIST-SORT, LIST-MAPCAR, ...

∂13-Jan-85  1322	JAR@MIT-MC 	list-length  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Jan 85  13:21:53 PST
Date: 13 January 1985 16:22-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  list-length
To: willc%indiana.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of Fri 4 Jan 85 15:50:17 est from Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

    Date: Fri, 4 Jan 85 15:50:17 est
    From: Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

    Pardon me, but I am not certain whether your recent message (LIST-APPEND,
    LIST-REVERSE, LIST-SORT, LIST-MAPCAR, ...) was in support of or in derision
    of the proposal that the operations on lists be prefixed by LIST- .

Neither, really.  The intent of the message was to ask "where do you
draw the line?".  E.g.  APPEND / STRING-APPEND have the same problem that
LENGTH / STRING-LENGTH do.  If you're not careful you end up putting
data type prefixes on everything (as you might have to in a strongly typed
language without unions, like PASCAL) or nothing (as in a fully generic
language like Smalltalk).  What policy should we adopt?

∂13-Jan-85  1328	KMP@MIT-MC 	policy to adopt   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Jan 85  13:28:24 PST
Date: 13 January 1985 16:28-EST
From: Kent M Pitman <KMP @ MIT-MC>
Subject: policy to adopt
To: SCHEME @ MIT-MC

i think we should clearly re-emphasize what our rationale is for wanting
any standard before deciding a policy. if the only purpose is to be able
to write papers that use common syntax, the policy might want to be different
than if we plan to port code. as much as we are not trying to make a
Common Scheme, some of the trends in this discussion have leaned pretty
strongly in that direction, perhaps overly so in some cases. i can elaborate
if it becomes appropriate to do so; i'll let it go at that for now.
-kmp

∂13-Jan-85  2117	@MIT-MC:CPH@MIT-OZ 	Scheme String Operations: the Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Jan 85  21:17:18 PST
Date: Mon, 14 Jan 1985  00:17 EST
Message-ID: <CPH.12079391220.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>,
      Jensen%ti-csl.csnet@CSNET-RELAY.ARPA,
      Oxley%ti-csl.csnet@CSNET-RELAY.ARPA, Scheme@MIT-MC
Subject: Scheme String Operations: the Report
In-reply-to: Msg of 13 Jan 1985  15:14-EST from CPH

Here is the preliminary report...  Comments and suggestions?

----------------------------------------------------------------------

                       Scheme String Operations


Notes:

[] Strings are mutable vectors of characters.

[] The string datatype described here has very little dependence on
the character datatype from which it is built.  Thus it may correspond
to either of Common Lisp's STRING or SIMPLE-STRING datatypes.  In MIT
Scheme, the character datatype is a special extended ASCII.

[] Historically, two different methods have been used to specify
substrings: [1] a starting index and a length, and [2] a starting
index and an ending index.  Often both methods have been used for
different operations in the same data abstraction.
The arguments in favor of one method or the other seem fairly
uninteresting, but it does seem important to pick one method and use
it exclusively.  The latter method has been chosen, for no
particularly good reason.


Naming conventions:

[] Character-wise operations are normally specified in two forms, one
which operates on a substring, and another which operates on an entire
string.  The former is usually named "SUBSTRING-..." and the latter
"STRING-...".

[] Operations for which case sensitivity has meaning are specified in
two forms, a case-sensitive version and a case-insensitive version.
The latter is given the suffix "-CI" to distinguish it; if the
operation is a predicate, the suffix precedes the "?" at the end of
the name.

[] Currently, operation pairs which are "directed" will be given
similar names, such as, "STRING-FIND-NEXT-CHAR" and
"STRING-FIND-PREVIOUS-CHAR".  However, there are 3 different syllable
pairs used to distinguish these operations: "LEFT"/"RIGHT",
"PREVIOUS"/"NEXT", and "FORWARD"/"BACKWARD".  In each case the
particular pair was chosen for its meaning, but it may be better to
name them more consistently.
!
----------------------------------------------------------------------

                             Definitions


[] The phrases "X is a string" and "the string X" mean that X is an
object which satisfies the STRING? predicate.  Similarly, "X is a
character" means that X satisfies the CHAR? predicate.

[] The "length" of a string is the number of characters that it
contains.  This number is a non-negative integer that is determined at
the time of the string's creation.

[] The phrase "X is a valid index of Y", where Y is a string, means
that X is a non-negative integer that is strictly less than the length
of Y.  The index 0 refers to the first character, 1 to the second,
etc.

[] The phrase "<X,Y,Z> is a substring" means that:

    1.  X is a string.
    2.  Both Y and Z are non-negative integers.
    3.  Z is less than or equal to the length of X.
    4.  Y is less than or equal to Z.

This refers to that substring of X starting at Y (inclusive) and
ending at Z (exclusive).  If Y is equal to Z, the substring is empty.

[] The directions "left" and "right" refer to numerically decreasing
and numerically increasing indices, respectively.  Alternate names for
these directions are (respectively): "previous" and "next"; "backward"
and "forward".
!
----------------------------------------------------------------------

                      Basic Character Operations


These are the operations on characters that are required by the string
data abstraction.  The names of these operations are irrelevant; only
the functionality is required.


(CHAR-EQUAL? CHAR1 CHAR2)
(CHAR-EQUAL-CI? CHAR1 CHAR2)

These predicates are true iff CHAR1 and CHAR2 are the same character.
The former operation is case sensitive, while the latter is not.  Both
CHAR1 and CHAR2 must be characters.

(CHAR-LESS? CHAR1 CHAR2)
(CHAR-LESS-CI? CHAR1 CHAR2)

These predicates are true iff CHAR1 is strictly less than CHAR2 in the
character ordering.  The former operation is case sensitive, while the
latter is not.  Both CHAR1 and CHAR2 must be characters.


(CHAR-UPPER-CASE? CHAR)
(CHAR-LOWER-CASE? CHAR)

These predicates should be true only of upper and lower case
alphabetic characters, respectively.  CHAR must be a character.


(CHAR-UPCASE CHAR)
(CHAR-DOWNCASE CHAR)

These operations convert alphabetic characters to upper and lower
case, respectively.  If CHAR is not alphabetic, it is returned.  CHAR
must be a character.


                            Character-sets


A character-set is an abstract object that represents a (mathematical)
set of characters.  Character-set searches are most useful for parsing
strings.  The required operations on character-sets are:


(CHAR-SET-MEMBER? CHAR-SET CHAR)

A predicate which is true iff the character CHAR is a member of the
character-set CHAR-SET.
!
----------------------------------------------------------------------

                       Basic String Operations


These are the most primitive of the string operations.  All other
string operations can be constructed from these.


(STRING-ALLOCATE LENGTH)

This operation allocates a new string, of the given LENGTH, and
returns it.  The contents of the string are unspecified.  LENGTH must
be a non-negative integer.


(STRING? OBJECT)

This is a boolean operation which is true of all strings.

(STRING-LENGTH STRING)

This operation returns the length of STRING, which must be a string.
The value is a non-negative integer.


(STRING-REF STRING INDEX)

This operation returns the INDEX'th element of STRING, a character.
STRING must be a string, and INDEX must be a valid index of STRING.


(STRING-SET! STRING INDEX CHAR)

This operation stores the character CHAR as the INDEX'th element of
STRING.  STRING must be a string, INDEX must be a valid index of
STRING, and CHAR must be a character.
!
----------------------------------------------------------------------

                         Standard Operations


These operations are useful enough to deserve being "standard" in most
implementations.


(MAKE-STRING LENGTH CHAR)

This allocates a new string of the given LENGTH, and initializes all
of its elements to CHAR.  LENGTH must be a non-negative integer, and
CHAR must be a character.


(STRING-FILL! STRING CHAR)

This fills the string STRING with the character CHAR.


(STRING-NULL? STRING)

This predicate is true only of strings whose length is zero.  STRING
must be a string.


(SUBSTRING STRING START END)

This operation returns a new string, which is the substring designated
by <STRING, START, END>; this must be a valid substring designator.


(STRING-APPEND STRING1 STRING2)

This operation returns a new string, which is the concatenation of
STRING1 followed by STRING2, both of which must be strings.  This
operation may (optionally) be n-ary, for n greater than 0.


(STRING-COPY STRING)

This operation returns a new copy of STRING, which must be a string.


(STRING->LIST STRING)
(LIST->STRING CHARS)

These operations convert between strings and lists of characters.
STRING must be a string, and CHARS must be a list of characters.  The
result of either operation is a newly-created object of the
appropriate form.
!
----------------------------------------------------------------------

                          Motion Primitives


These operations are useful because they can be used to construct many
other string operations, e.g. SUBSTRING and STRING-APPEND.  If strings
are implemented in the usual way on conventional machines, these
operations are extremely simple to implement.  It is also possible to
in-line code them in some cases.


(SUBSTRING-FILL! STRING START END CHAR)

This fills the substring <STRING, START, END> with the character CHAR.


(SUBSTRING-MOVE-RIGHT! STRING1 START1 END1 STRING2 START2)
(SUBSTRING-MOVE-LEFT! STRING1 START1 END1 STRING2 START2)

These operations destructively copy the substring <STRING1, START1,
END1> to the string STRING2 starting at the index START2.  It must be
the case that <STRING2, START2, (+ START2 (- END1 START1))> is a
substring; this latter substring is destructively modified to contain
the contents of the former substring.

The operations differ only when the two substrings overlap, i.e. when
STRING1 and STRING2 are EQ? and the index sets of the substrings are
not disjoint.  In this case, the operations are defined to copy the
elements of the first substring serially.  SUBSTRING-MOVE-RIGHT!
copies the first substring from left to right, while
SUBSTRING-MOVE-LEFT! copies from right to left.  Thus, for example,
the two operations can be used to shift groups of characters right or
left, respectively, within a given string.
!
----------------------------------------------------------------------

                        Comparison Primitives


Each group of comparisons contains these operations:

    1.  Compare two substrings, case sensitive.
    2.  Compare two strings, case sensitive.
    3.  Compare two substrings, case insensitive.
    4.  Compare two strings, case insensitive.

The groups are described as a unit since they are essentially very
similar.  In all cases the arguments must be valid substrings or
strings.

(SUBSTRING-EQUAL? STRING1 START1 END1 STRING2 START2 END2)
(STRING-EQUAL? STRING1 STRING2)
(SUBSTRING-EQUAL-CI? STRING1 START1 END1 STRING2 START2 END2)
(STRING-EQUAL-CI? STRING1 STRING2)

These are boolean equality predicates, which are true only when the
two (sub)strings are the same length and contain the same characters.


(SUBSTRING-LESS? STRING1 START1 END1 STRING2 START2 END2)
(STRING-LESS? STRING1 STRING2)
(SUBSTRING-LESS-CI? STRING1 START1 END1 STRING2 START2 END2)
(STRING-LESS-CI? STRING1 STRING2)

These are boolean order predicates, which compare the (sub)strings
using the standard dictionary order; i.e. the leftmost unequal
characters determine the order, or if no such character exists, the
shorter (sub)string is less.  The character ordering is determined by
the character operations CHAR-LESS? and CHAR-LESS-CI?.


(SUBSTRING-MATCH-FORWARD STRING1 START1 END1 STRING2 START2 END2)
(STRING-MATCH-FORWARD STRING1 STRING2)
(SUBSTRING-MATCH-FORWARD-CI STRING1 START1 END1 STRING2 START2 END2)
(STRING-MATCH-FORWARD-CI STRING1 STRING2)

These operations compare the (sub)strings from left to right,
returning the number of characters that were the same.

(SUBSTRING-MATCH-BACKWARD STRING1 START1 END1 STRING2 START2 END2)
(STRING-MATCH-BACKWARD STRING1 STRING2)
(SUBSTRING-MATCH-BACKWARD-CI STRING1 START1 END1 STRING2 START2 END2)
(STRING-MATCH-BACKWARD-CI STRING1 STRING2)

These operations compare the (sub)strings from right to left,
returning the number of characters that were the same.
!
----------------------------------------------------------------------

                     Character Search Primitives


Each group of searches contains these operations:

    1.  Search substring for character, case sensitive.
    2.  Search string for character, case sensitive.
    3.  Search substring for character, case insensitive.
    4.  Search string for character, case insensitive.
    5.  Search substring for character in set.
    6.  Search string for character in set.

In all cases the arguments must be valid substrings, strings,
characters, or character-sets, as appropriate.


(SUBSTRING-FIND-NEXT-CHAR STRING START END CHAR)
(STRING-FIND-NEXT-CHAR STRING CHAR)
(SUBSTRING-FIND-NEXT-CHAR-CI STRING START END CHAR)
(STRING-FIND-NEXT-CHAR-CI STRING CHAR)
(SUBSTRING-FIND-NEXT-CHAR-IN-SET STRING START END CHAR-SET)
(STRING-FIND-NEXT-CHAR-IN-SET STRING CHAR-SET)

These operations return the index of the leftmost occurrence of the
character CHAR (or character-set CHAR-SET) within the given
(sub)string, or #!FALSE if there is no occurrence.


(SUBSTRING-FIND-PREVIOUS-CHAR STRING START END CHAR)
(STRING-FIND-PREVIOUS-CHAR STRING CHAR)
(SUBSTRING-FIND-PREVIOUS-CHAR-CI STRING START END CHAR)
(STRING-FIND-PREVIOUS-CHAR-CI STRING CHAR)
(SUBSTRING-FIND-PREVIOUS-CHAR-IN-SET STRING START END CHAR-SET)
(STRING-FIND-PREVIOUS-CHAR-IN-SET STRING CHAR-SET)

These operations return the index of the rightmost occurrence of the
character CHAR (or character-set CHAR-SET) within the given
(sub)string, or #!FALSE if there is no occurrence.
!
----------------------------------------------------------------------

                                 Case


Each of the following groups contains the following operations:

    1.  A predicate to determine a substring's case.
    2.  A predicate to determine a string's case.
    3.  A operation to destructively set a substring's case.
    4.  A operation to destructively set a string's case.

The meanings of the operations should be clear from their names.


(SUBSTRING-UPPER-CASE? STRING START END)
(STRING-UPPER-CASE? STRING)
(SUBSTRING-UPCASE! STRING START END)
(STRING-UPCASE! STRING)

(SUBSTRING-LOWER-CASE? STRING START END)
(STRING-LOWER-CASE? STRING)
(SUBSTRING-DOWNCASE! STRING START END)
(STRING-DOWNCASE! STRING)

(SUBSTRING-CAPITALIZED? STRING START END)
(STRING-CAPITALIZED? STRING)
(SUBSTRING-CAPITALIZE! STRING START END)
(STRING-CAPITALIZE! STRING)

The (sub)string in the ...CAPITALIZE... operations may not be null.
!
----------------------------------------------------------------------

                     Appendix: An Implementation


The following is an examplary implementation of the above string
operations (in terms of the basic operations).  This implementation is
intended to supplement the preceding specification by providing an
explicit formal description of the semantics of the operations.

There is no error checking in this code, since it was felt that it
would obscure the form somewhat.
!
;;;; Standard Operations

(define (make-string length char)
  (let ((result (string-allocate length)))
    (substring-fill! result 0 length char)
    result))

(define (string-fill! string char)
  (substring-fill! string 0 (string-length string) char))

(define (string-null? string)
  (zero? (string-length string)))

(define (substring string start end)
  (let ((result (string-allocate (- end start))))
    (substring-move-right! string start end result 0)
    result))

(define (string-append string1 string2)
  (let ((length1 (string-length string1))
	(length2 (string-length string2)))
    (let ((result (string-allocate (+ length1 length2))))
      (substring-move-right! string1 0 length1 result 0)
      (substring-move-right! string2 0 length2 result length1)
      result)))

(define (string-copy string)
  (let ((length (string-length string)))
    (let ((result (string-allocate length)))
      (substring-move-right! string 0 length result 0)
      result)))

(define (string->list string)
  (let ((end (string-length string)))
    (define (loop index)
      (if (= index end)
	  '()
	  (cons (string-ref string index)
		(loop (1+ index)))))
    (loop 0)))

(define (list->string chars)
  (let ((result (string-allocate (length chars))))
    (define (loop index chars)
      (if (null? chars)
	  result
	  (begin (string-set! result index (car chars))
		 (loop (1+ index) (cdr chars)))))
    (loop 0 chars)))
!
;;;; Motion Primitives

(define (substring-fill! string start end char)
  (define (loop index)
    (if (not (= index end))
	(begin (string-set! string index char)
	       (loop (1+ index)))))
  (loop start))

(define (substring-move-right! string1 start1 end1 string2 start2)
  (define (loop index1 index2)
    (if (not (= index1 end1))
	(begin (string-set! string2 index2 (string-ref string1 index1))
	       (loop (1+ index1) (1+ index2)))))
  (loop start1 start2))

(define (substring-move-left! string1 start1 end1 string2 start2)
  (define (loop index1 index2)
    (if (not (= index1 start1))
	(begin (string-set! string2
			    (-1+ index2)
			    (string-ref string1 (-1+ index1)))
	       (loop (-1+ index1) (-1+ index2)))))
  (loop end1 end2))
!
;;;; Comparison Primitives

(define substring-equal?)
(define substring-equal-ci?)

(let ()
  (define (make-substring-equal? char-equal?)
    (lambda (string1 start1 end1 string2 start2 end2)
      (define (loop index1 index2)
	(or (= index1 end1)
	    (and (char-equal? (string-ref string1 index1)
			      (string-ref string2 index2))
		 (loop (1+ index1) (1+ index2)))))
      (and (= (- end1 start1) (- end2 start2))
	   (loop start1 start2))))
  (set! substring-equal?
	(make-substring-equal? char-equal?))
  (set! substring-equal-ci?
	(make-substring-equal? char-equal-ci?)))

(define substring-less?)
(define substring-less-ci?)

(let ()
  (define (make-substring-less? char-equal? char-less?)
    (lambda (string1 start1 end1 string2 start2 end2)
      (define (loop index1 index2)
	(cond ((or (= index1 end1)
		   (= index2 end2))
	       (< (- end1 start1)
		  (- end2 start2)))
	      ((char-equal? (string-ref string1 index1)
			    (string-ref string2 index2))
	       (loop (1+ index1) (1+ index2)))
	      (else
	       (char-less? (string-ref string1 index1)
			   (string-ref string2 index2)))))
      (loop start1 start2)))
  (set! substring-less?
	(make-substring-less? char-equal? char-less?))
  (set! substring-less-ci?
	(make-substring-less? char-equal-ci? char-less-ci?)))

(define substring-match-forward)
(define substring-match-forward-ci)

(let ()
  (define (make-substring-match-forward char-equal?)
    (lambda (string1 start1 end1 string2 start2 end2)
      (define (loop index1 index2 n)
	(if (or (= index1 end1)
		(= index2 end2)
		(not (char-equal? (string-ref string1 index1)
				  (string-ref string2 index2))))
	    n
	    (loop (1+ index2) (1+ index2) (1+ n))))
      (loop start1 start2 0)))
  (set! substring-match-forward
	(make-substring-match-forward char-equal?))
  (set! substring-match-forward-ci
	(make-substring-match-forward char-equal-ci?)))
!
(define substring-match-backward)
(define substring-match-backward-ci)

(let ()
  (define (make-substring-match-backward char-equal?)
    (lambda (string1 start1 end1 string2 start2 end2)
      (define (loop index1 index2 n)
	(if (or (= index1 start1)
		(= index2 start2)
		(not (char-equal? (string-ref string1 (-1+ index1))
				  (string-ref string2 (-1+ index2)))))
	    n
	    (loop (-1+ index2) (-1+ index2) (1+ n))))
      (loop end1 end2 0)))
  (set! substring-match-backward
	(make-substring-match-backward char-equal?))
  (set! substring-match-backward-ci
	(make-substring-match-backward char-equal-ci?)))

(define string-equal?)
(define string-equal-ci?)
(define string-less?)
(define string-less-ci?)
(define string-match-forward)
(define string-match-forward-ci)
(define string-match-backward)
(define string-match-backward-ci)

(let ()
  (define (string-comparison substring-comparison)
    (lambda (string1 string2)
      (substring-comparison string1 0 (string-length string1)
			    string2 0 (string-length string2))))
  (set! string-equal?
	(string-comparison substring-equal?))
  (set! string-equal-ci?
	(string-comparison substring-equal-ci?))
  (set! string-less?
	(string-comparison substring-less?))
  (set! string-less-ci?
	(string-comparison substring-less-ci?))
  (set! string-match-forward
	(string-comparison substring-match-forward))
  (set! string-match-forward-ci
	(string-comparison substring-match-forward-ci))
  (set! string-match-backward
	(string-comparison substring-match-backward))
  (set! string-match-backward-ci
	(string-comparison substring-match-backward-ci)))
!
;;;; Character Search Primitives

(define substring-find-next-char)
(define substring-find-next-char-ci)
(define substring-find-next-char-in-set)

(let ()
  (define (find-next char-test)
    (lambda (string start end key)
      (define (loop index)
	(and (not (= index end))
	     (if (char-test key (string-ref string index))
		 index
		 (loop (1+ index)))))
      (loop start)))
  (set! substring-find-next-char (find-next char-equal?))
  (set! substring-find-next-char-ci (find-next char-equal-ci?))
  (set! substring-find-next-char-in-set (find-next char-set-member?)))

(define substring-find-previous-char)
(define substring-find-previous-char-ci)
(define substring-find-previous-char-in-set)

(let ()
  (define (find-previous char-test)
    (lambda (string start end key)
      (define (loop index)
	(and (not (= index start))
	     (let ((index (-1+ index)))
	       (if (char-test key (string-ref string index))
		   index
		   (loop index)))))
      (loop end)))
  (set! substring-find-previous-char (find-previous char-equal?))
  (set! substring-find-previous-char-ci (find-previous char-equal-ci?))
  (set! substring-find-previous-char-in-set (find-previous char-set-member?)))

(define string-find-next-char)
(define string-find-next-char-ci)
(define string-find-next-char-in-set)
(define string-find-previous-char)
(define string-find-previous-char-ci)
(define string-find-previous-char-in-set)

(let ()
  (define (string-search substring-search)
    (lambda (string char)
      (substring-search string 0 (string-length string) char)))
  (set! string-find-next-char
	(string-search substring-find-next-char))
  (set! string-find-next-char-ci
	(string-search substring-find-next-char-ci))
  (set! string-find-next-char-in-set
	(string-search substring-find-next-char-in-set))
  (set! string-find-previous-char
	(string-search substring-find-previous-char))
  (set! string-find-previous-char-ci
	(string-search substring-find-previous-char-ci))
  (set! string-find-previous-char-in-set
	(string-search substring-find-previous-char-in-set)))
!
;;;; Case

(define substring-upper-case?)
(define substring-lower-case?)

(let ()
  (define (substring-has-case? char-has-case?)
    (lambda (string start end)
      (define (loop index)
	(or (= index end)
	    (and (char-has-case? (string-ref string index))
		 (loop (1+ index)))))
      (loop start)))
  (set! substring-upper-case?
	(substring-has-case? char-upper-case?))
  (set! substring-lower-case?
	(substring-has-case? char-lower-case?)))

(define substring-upcase!)
(define substring-downcase!)

(let ()
  (define (substring-set-case! char-set-case)
    (lambda (string start end)
      (define (loop index)
	(if (not (= index end))
	    (begin (string-set! string
				index
				(char-set-case (string-ref string index)))
		   (loop (1+ index)))))
      (loop start)))
  (set! substring-upcase!
	(substring-set-case! char-upcase))
  (set! substring-downcase!
	(substring-set-case! char-downcase)))

(define (substring-capitalized? string start end)
  (define (loop end)
    (or (= end end)
	(and (char-lower-case? (string-ref string end))
	     (loop (1+ end)))))
  (and (not (= start end))
       (char-upper-case? (string-8b-ref string 0))
       (loop (1+ start))))

(define (substring-capitalize! string start end)
  (substring-upcase! string start (1+ start))
  (substring-downcase! string (1+ start) end))

(define string-upper-case?)
(define string-lower-case?)
(define string-upcase!)
(define string-downcase!)
(define string-capitalized?)
(define string-capitalize!)

(let ()
  (define (string-op substring-op)
    (lambda (string)
      (substring-op string 0 (string-length string))))
  (set! string-upper-case?
	(string-op substring-upper-case?))
  (set! string-lower-case?
	(string-op substring-lower-case?))
  (set! string-upcase!
	(string-op substring-upcase!))
  (set! string-downcase!
	(string-op substring-downcase!))
  (set! string-capitalized?
	(string-op substring-capitalized?))
  (set! string-capitalize!
	(string-op substring-capitalize!)))

∂14-Jan-85  0217	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  policy to adopt
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Jan 85  02:16:54 PST
Received: from unc by csnet-relay.csnet id a000234; 14 Jan 85 5:09 EST
Received: by unc (4.12/4.7) id AA00749; Sun, 13 Jan 85 22:21:36 est
Date: Sun, 13 Jan 85 22:21:36 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8501140321.AA00749@unc>
To: KMP@mit-mc.ARPA, SCHEME@mit-mc.ARPA
Subject: Re:  policy to adopt

I have certainly gotten the impression that everyone WAS after
a Common Scheme of sorts, and not just so that papers use common
syntax.  Why standardize on so many of the function names?  More
importantly, why standardize on the controversial nil/t/boolean
issue?  Why have numbers and streams subcommittees?

I think we need more discussion of the details of the proposal
rather than less.  Standardizing is dangerous if done only half-
heartedly.  We must be absolutely sure of what we standardize on,
since we will likely be stuck with our decisions for several
years.

As for the list-length, list-append issue, I think we ought to take
one of two stances:

	Stance 1:  sequence-type functions such as ref, length and
		   append should be prefixed by "list-" for the
		   list version, "string-" for the string version, 
		   and "vector-" for the vector version.

	Stance 2:  sequence-type functions such as ref, length and
		   append should be prefixed by nothing for the
		   list version, "string-" for the string version,
		   and "vector-" for the vector version.

The first stance is preferable because of the symmetry, the second
because the names for the list versions (probably the most commonly
used) are shorter.  I think that the first stance is less confusing
and less likely to cause trouble.

    Cheers,
	Kent Dybvig


∂15-Jan-85  1914	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Scheme String Operations: the Report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Jan 85  19:14:04 PST
Received: from ti-csl by csnet-relay.csnet id ab07537; 15 Jan 85 22:01 EST
Date: 15 Jan 1985 1445-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: Scheme String Operations: the Report
To: CPH%MIT-OZ@mit-mc.ARPA, Bartley%ti-csl.csnet@csnet-relay.arpa, 
    Jensen%ti-csl.csnet@csnet-relay.arpa, Oxley%ti-csl.csnet@csnet-relay.arpa, 
    Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 14-Jan-85 0529-CST
Received: from csl60 by ti-csl; Tue, 15 Jan 85 20:45 CST

Chris,

  Thanks for mailing out the preliminary report on your proposal for string
operations for Scheme.  Here are my initial reactions.

  -- You were clearly influenced by Common LISP (CL), since at least 27 of
your functions have direct analogues in CL.  You rarely use the same name
as CL uses, however.  I tend to agree with most of your name choices, with
one exception: CL uses the suffixes =, <, etc. for case sensitive
comparisons of characters and strings and the suffixes EQUAL, LESSP, etc
for case-insensitive comparisons.  I prefer to adopt that convention rather
than inventing the suffix -CI.

We should definitely preserve our conventions regarding suffixed ?  and !
characters.  Thus, CL's CHAR-LESSP and NSTRING-UPCASE should be renamed
CHAR-LESS? and STRING-UPCASE! for Scheme.

  -- We probably need a (CHAR? obj) predicate.  The following are useful;
can we agree on their meaning?

	(CHAR->INTEGER char)	; CL's CHAR-CODE ?
	(INTEGER->CHAR n)	; CL's CODE-CHAR ?

  -- The order of arguments to CHAR-SET-MEMBER? is reversed from that of
MEMBER, MEMV, and MEMQ.

  -- How is a CHAR-SET represented?  Created?  Modified?

  -- Why distinguish STRING-ALLOCATE from MAKE-STRING?  By analogy with
MAKE-VECTOR, shouldn't MAKE-STRING take the second argument optionally?

  -- May I assume that string and character values are printed (and read)
as defined by CL?

  -- May I assume that all of the operations you defined are procedures,
not special forms?

  -- May I assume that SUBSTRING and other names written without ! always
return a copy rather than sharing structure?

  -- One way to reduce the number of operations is to combine the STRING-
and SUBSTRING- operations by accepting optional substring operands.  For
example, specify only

		(STRING-FILL!     string  char  { start { end }} )
instead of
		(STRING-FILL!     string  char)			and
and		(SUBSTRING-FILL!  string  start  end  char)

Note that the <char> argument has been repositioned.

It would be useful to let either <start> or <end> default.  In the example
above, we could interpret

		(STRING-FILL!  string  char  start)

as filling from <start> to the end of the string.

  -- What should happen when indexes cross (start>end) or go outside the
proper range?

  -- Are you suggesting that the Basic Character Operations, Basic String
Operations, and Standard Operations be 'required' and the rest be
'optional'?  If not, where would you draw the line?  Do you use all of
these operations yourself?

  -- Is the character datatype in MIT Scheme extended the same way CL has
gone?  Do you support font and/or bit info?  Have you added operations to
MIT Scheme beyond those you've proposed in your report?

  -- In summary, the proposal looks sound and I have no arguments with the
functionality you are proposing.  I'll pass on further comments after we've
had time to digest it more thoroughly.

Regards,
David Bartley
-------


∂15-Jan-85  2339	@MIT-MC:CPH@MIT-OZ 	Scheme String Operations: the Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Jan 85  23:38:57 PST
Date: Wed, 16 Jan 1985  02:40 EST
Message-ID: <CPH.12079941473.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Jensen%ti-csl.csnet@CSNET-RELAY.ARPA,
      Oxley%ti-csl.csnet@CSNET-RELAY.ARPA, Scheme@MIT-MC.ARPA
Subject: Scheme String Operations: the Report
In-reply-to: Msg of 15 Jan 1985  15:45-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    Date: Tuesday, 15 January 1985  15:45-EST
    From: David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

      -- We probably need a (CHAR? obj) predicate.  The following are useful;
    can we agree on their meaning?

    	(CHAR->INTEGER char)	; CL's CHAR-CODE ?
    	(INTEGER->CHAR n)	; CL's CODE-CHAR ?

      -- How is a CHAR-SET represented?  Created?  Modified?

      -- Is the character datatype in MIT Scheme extended the same way CL has
    gone?  Do you support font and/or bit info?  Have you added operations to
    MIT Scheme beyond those you've proposed in your report?

In answer to all of these:  I purposefully limited my description of
characters (and character sets) to that minimum required to describe
the string abstraction.  I did this because I felt that the string
abstraction was very largely independent of the character abstraction;
this method shows the dependence pretty clearly.

Further, I recall that we agreed to do characters "the CL way" at the
workshop, at least so far as syntax.  My character datatype is heavily
influenced by CL, and implements bits but not fonts (I don't need them
now).  I would be willing to discuss both this and the character set
abstraction if there is interest.


      -- You were clearly influenced by Common LISP (CL)...

Not so!  The string operations were mostly designed from scratch; I
was unaware that they were so similar.


    ...CL uses the suffixes =, <, etc. for case sensitive
    comparisons of characters and strings and the suffixes EQUAL, LESSP, etc
    for case-insensitive comparisons.  I prefer to adopt that convention...

Mumble.  I don't particularly like those names, but then, I don't
particularly care about the names anyway.  I'm not terribly happy with
the names I chose, either.  Whatever folks like is fine with me.


      -- May I assume that string and character values are printed (and read)
    as defined by CL?

Yes; I think that we agreed upon this at the workshop.


      -- May I assume that all of the operations you defined are procedures,
    not special forms?

Yes!!! (with feeling)


      -- May I assume that SUBSTRING and other names written without ! always
    return a copy rather than sharing structure?

Yes.  Furthermore, operations written with a "!" return undefined values.


      -- Why distinguish STRING-ALLOCATE from MAKE-STRING?  By analogy with
    MAKE-VECTOR, shouldn't MAKE-STRING take the second argument optionally?

      -- One way to reduce the number of operations is to combine the STRING-
    and SUBSTRING- operations by accepting optional substring operands.

Gee, I guess that I don't feel too good about that.  While it is true
that this cuts down on the number of names, I have an irrational fear
of widespread optionalogy.  Perhaps it is from overexposure to
flagrant misuse, but I prefer not to use optionals at the "lower
levels" of my code.

Also, I was particularly thinking about the workshop, and I recall
there was very mixed feeling about optional arguments, rest arguments,
etc... I felt that this would be more acceptable to the community as a
whole.


      -- The order of arguments to CHAR-SET-MEMBER? is reversed from that of
    MEMBER, MEMV, and MEMQ.

Hmm... This was chosen to match other stuff... in particular,
VECTOR-REF, LIST-REF, etc.  The convention is: the compound structure
first, the key second.  In hindsight, it clearly should match MEMfoo.


      -- What should happen when indexes cross (start>end) or go outside the
    proper range?

Sorry, I should have spelled that out.  It will signal an error, in
all cases (although maybe not at the most reasonable place, in my
implementation).  I specific: everywhere where I have described the
arguments as "a string", "a character", "a substring", etc., those can
be construed as requirements.  Errors will happen if those things are
not true.


      -- Are you suggesting that the Basic Character Operations, Basic String
    Operations, and Standard Operations be 'required' and the rest be
    'optional'?  If not, where would you draw the line?  Do you use all of
    these operations yourself?

No, I was making no such suggestion; I would be hesitant to do so
without some discussion.  I do feel that the 'Basic String Operations'
and 'Standard Operations', with the exception of STRING-ALLOCATE,
STRING-SET!, and STRING-FILL!, are very useful, and perhaps should be
required.  But then we have already agreed upon those in the 'Basic'
category, and I think that there would be little disagreement about
the 'Standard' ones.

But I can't really say where one should draw the line; all of these
procedures are useful if one ever does anything even moderately hairy.
Personally, I have used most of these operations pretty freely in the
editor.

I have found, though, that a particular pattern has emerged.  The
mutating operations are used (in conjunction with STRING-ALLOCATE)
almost exclusively for the construction of higher level, non-mutating
operations like SUBSTRING and STRING-APPEND.  I think that such things
might safely be relegated to the realm of 'system programming', for
those who prefer to make such a distinction.

Anyway, if there is interest in working out the boundaries of
'required' vs. 'optional' here, I am perfectly willing to add more of
my flame to the conflagration.

∂24-Jan-85  1227	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Purpose of a "common" Scheme 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Jan 85  12:00:43 PST
Received: from indiana by csnet-relay.csnet id aa09096; 24 Jan 85 14:38 EST
Date: Thu, 24 Jan 85 13:27:13 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA11826; Thu, 24 Jan 85 13:27:13 est
To: scheme@mit-mc.ARPA
Subject: Purpose of a "common" Scheme

Surely different people have different purposes in wanting a more
standardized Scheme.  Half the fun is getting everyone to work
together and to agree.  It helps to be vague about the purposes.
Here's my view, from a draft introduction to the final report on
the workshop:

    Scheme shares with Common Lisp [\ref] the goal of a core
    language common to several implementations.  Scheme differs
    from Common Lisp in that the purpose of the common language
    has more to do with porting ideas than with porting code.
    It is appropriate therefore that Scheme is much smaller, is
    less pervasively specified, and will evolve faster than
    Common Lisp.

Let me know by direct mail if you object to that wording.

				William Clinger (willc@indiana)


∂31-Jan-85  0921	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Resources for Scheme course    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Jan 85  09:17:38 PST
Received: from brandeis by csnet-relay.csnet id a002562; 31 Jan 85 12:13 EST
Received: by brandeis.ARPA (4.12/4.7)
	id AA14346; Thu, 31 Jan 85 10:14:16 est
Date: 31 Jan 1985 09:53-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: Resources for Scheme course
To: scheme@mit-mc.ARPA, cth%indiana.csnet@csnet-relay.arpa
Cc: jc%brandeis.csnet@csnet-relay.arpa
Message-Id: <476031183/mw@brandeis>

Brandeis is currently considering creating a laboratory facility for a
course on the style of the Abelson & Sussman book.  For this purpose, I
am collecting data on the state of various workstation implementations
of Scheme and related languages (e.g. T).  I know about some
implementations, but I'd like to hear about others, and get up-to-date
information even about the ones I've heard of.  In particular:

1) What workstations would you recommend for such an undertaking, and
what is the availability of appropriate software?

2) What ratio of students/workstation would you recommend?  To give
some idea of the planned intensity of the course, let's assume that we
plan to cover about half of the material in A&S in a semester.

3) How many square feet per workstation should we plan on?  What other
things in the physical arrangment of the facility should we watch out
for?

Reply to mw@brandeis on csnet.  I will post a summary of replies to
the mailing list if interest warrants.  Thanks for your help.

-- Mitch Wand


∂01-Feb-85  0930	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	quotient, remainder, letrec  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 1 Feb 85  09:30:03 PST
Received: from indiana by csnet-relay.csnet id aa04954; 1 Feb 85 12:23 EST
Date: Fri, 1 Feb 85 11:13:53 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA02926; Fri, 1 Feb 85 11:13:53 est
To: scheme@mit-mc.ARPA
Subject: quotient, remainder, letrec

In the preliminary report on the Brandeis workshop, I said that quotient and
remainder were such that if x, y, q, and r are integers such that x = qy +
r, y is nonzero, r has the same sign as y and has absolute value less than
that of y, then (quotient x y) was q and (remainder x y) was r.  Since that
conflicts with Common Lisp, Franz Lisp, T, Scheme 84, Scheme 312, and maybe
MIT Scheme (my documentation on MIT Scheme isn't clear on the issue), I
retract that definition in favor of:

If x, y, q, and r are integers such that x = qy + r, y is nonzero, r has the
same sign as x, and |r| < |y|, then (quotient x y) is q and
(remainder x y) is r.

The definition of letrec in the preliminary report is wrong.

				William Clinger
				willc@indiana


∂02-Feb-85  1040	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Scheme String Operations    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 2 Feb 85  10:39:59 PST
Received: from ti-csl by csnet-relay.csnet id ah03968; 2 Feb 85 10:36 EST
Date:  1 Feb 1985 1453-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Scheme String Operations
To: Scheme@mit-mc.ARPA, CPH%MIT-OZ@mit-mc.ARPA
cc: SCHEME.Users%ti-csl.csnet@csnet-relay.arpa, 
    Bartley%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Fri, 1 Feb 85 16:57 CST

We at Texas Instruments propose the following revisions to Chris Hanson's
preliminary report on Scheme string operations.  Our implementation has
already begun, so we would like to hear objections and other comments as
soon as possible.  Thanks!


1. Name changes

   For reasonable consistency with Common LISP, we propose the following
name changes:

      Preliminary report      Our proposal     Common LISP
      ==================      ============     ===========
	char-equal?		char=		char=
	char-equal-ci?		char-equal?	char-equal
        char-less?		char<		char<
        char-less-ci?		char-less?	char-lessp

        substring-equal?	substring=
        string-equal?		string=
        substring-equal-ci?	substring-equal?
        string-equal-ci?	string-equal?

        substring-less?		substring<
        string-less?		string<
        substring-less-ci?	substring-less?
        string-less-ci?		string-less?


2. Added features

   (CHAR? obj) is needed for argument checking, if nothing else.

   We agreed at the workshop to include SYMBOL->STRING and STRING->SYMBOL
as essential and STRING->UNINTERNED-SYMBOL as optional.


3. Changes

   CHAR-SET-MEMBER should take its arguments in the same order as MEMBER.


4. Essential features

   We are not sure how to separate ``essential'' from ``optional''
features, but will probably go with everything labeled ``minimal'' below.
Those labeled ``elective'' will be available but not part of the initial
load of the system.

Basic Character Operations

    minimal:   CHAR?, CHAR=, CHAR-EQUAL?, CHAR<, CHAR-LESS?,
               CHAR-UPCASE, CHAR-DOWNCASE
    elective:  CHAR-UPPER-CASE?, CHAR-LOWER-CASE?, CHAR-SET-MEMBER?

Basic String Operations

    minimal:   STRING?, STRING-LENGTH, STRING-REF, STRING-SET!,
               STRING->SYMBOL, STRING->UNINTERNED-SYMBOL, SYMBOL->STRING
    elective:  STRING-ALLOCATE

Standard Operations

    minimal:   MAKE-STRING, STRING-FILL!, STRING-NULL?, SUBSTRING,
               STRING-APPEND, STRING-COPY, STRING->LIST, LIST->STRING

Motion Primitives

    minimal:   SUBSTRING-FILL!, SUBSTRING-MOVE-RIGHT!, SUBSTRING-MOVE-LEFT!

Comparison Primitives

    minimal:   SUBSTRING=, STRING=, SUBSTRING-EQUAL?, STRING-EQUAL?,
               SUBSTRING<, STRING<, SUBSTRING-LESS?, STRING-LESS?

    elective:  SUBSTRING-MATCH-FORWARD,     STRING-MATCH-FORWARD,
               SUBSTRING-MATCH-FORWARD-CI,  STRING-MATCH-FORWARD-CI,
               SUBSTRING-MATCH-BACKWARD,    STRING-MATCH-BACKWARD,
               SUBSTRING-MATCH-BACKWARD-CI, STRING-MATCH-BACKWARD-CI

Character Search Primitives

    elective:  all

Case

    elective:  all

-- Regards,
   David Bartley
-------


∂03-Feb-85  1055	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  Scheme String Operations 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 3 Feb 85  10:55:37 PST
Received: from unc by csnet-relay.csnet id aa08903; 3 Feb 85 13:47 EST
Received: by unc (4.12/4.7) id AA06699; Sun, 3 Feb 85 11:59:27 est
Date: Sun, 3 Feb 85 11:59:27 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8502031659.AA06699@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  Scheme String Operations

1.  I prefer Chris Hanson's names over the Common Lisp or Bartley names.
    I find the CL names confusing and nonsensical.  Why does "char=" imply
    case sensitivity, and "char-equal" insensitivity?  The issue is also
    confused because CL does not define "equal" to use "char-equal" as is
    implied by the naming convention.

    I have been using Common Lisp for over a year since helping to bring
    Data General's system into existence.  Many of us get confused about
    which is which.  There would be no confusion with a suffix such as
    "-ci".  Except for possible commercial interests, I can see no benefit
    in copying the mistakes of Common Lisp.

2.  I would rather spell out the name "character" in all functions rather
    than use the shorter "char" but that's probably too much to ask.

3.  I wish there weren't so many string functions.  I think Chris Hanson
    was on the right track with the very primitive set that can be used to
    construct all the others.  Perhaps we should have that set plus
    "string-ref", "string-equal?", "string-less?" "string-equal-ci?",
    and "string-less-ci?", "string->list", and "list->string".

4.  I have a "string" function in my system that comes in handy --
        (string char1 char2 ... charN)  =>  string of char1 ... charN, N >= 0.
    For example:
        (string #\a #\b #\c) => "abc".
    This is easy to write as (lambda x (list->string x)).
    It is particularly useful when creating a cursor-addressing string to
    send to the tty.

5.  I do not view "string->symbol" and "symbol->string" as string functions.
    They are symbol creation and destructuring primitives.  In fact, I
    strongly object to the names since they are not analogous to other
    type-conversion functions such as "string->list" and "character->integer".
    I'll say more about this in a separate note.

6.  As far as optionality is concerned, I would like to see Scheme adopt
    an optional argument mechanism.  It reduces the namespace and is really
    quite easy to implement efficiently.  A function like "member" becomes
    completely general, allowing not only "eq?", "eqv?" and "equal?" tests
    but also any user-defined test.  However, until we have optional
    arguments that can be defined using a lambda expression, I do not
    think we should have primitives with optional arguments.  Either the
    language has them or it doesn't.


        Kent Dybvig
        decvax!mcnc!unc!dyb
        dyb.unc@Csnet-Relay


∂03-Feb-85  1059	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	string->symbol, symbol->string
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 3 Feb 85  10:57:50 PST
Received: from unc by csnet-relay.csnet id ab08903; 3 Feb 85 13:47 EST
Received: by unc (4.12/4.7) id AA06730; Sun, 3 Feb 85 12:00:27 est
Date: Sun, 3 Feb 85 12:00:27 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8502031700.AA06730@unc>
To: scheme@mit-mc.ARPA
Subject: string->symbol, symbol->string

"symbol->string" and "string->symbol functions are not analogous to
"list->string" or "string->list".

"list->string" converts the same data from one representation into
another, with no loss of information.  The same is true for "string->list",
"list->vector", "vector->list" and "character->integer".  

A symbol is more than just an alternate representation for a string.
It can be an identifier or keyword.  Some implementations allow symbols
to have property lists.  All of this information is lost in the conversion
from symbol to string, some is regained in the opposite conversion.
I tend to think of the name of a symbol as an attribute of that symbol.
"symbol->string" is more correctly called "symbol-name".

Furthermore, whereas one can expect "string->list" to return a new list
made up of unique cons-cells, "string->symbol" may return an existing
symbol.  The name "intern" is more appropriate for this functionality.
(Perhaps "hash-make-symbol" would be a better name.)

If making a unique, uninterned symbol is supported, the name "make-symbol"
is appropriate.  

If what we are really doing when we say "make-symbol" or "string->symbol"
was changing representations, then "string->symbol" would be fine.  But
it isn't a type conversion we are doing, it's symbol creation (or lookup).
It seems analogous to saying "make-vector" should be called "integer->vector"
because we are taking an integer, n, and returning a vector of length n.
The name is only one aspect of a symbol in much the same way that the length
is only one aspect of a vector.

        Kent Dybvig
        decvax!mcnc!unc!dyb
        dyb.unc@Csnet-Relay


∂04-Feb-85  0221	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Chez Scheme    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 4 Feb 85  02:21:10 PST
Received: from unc by csnet-relay.csnet id aa11924; 4 Feb 85 5:13 EST
Received: by unc (4.12/4.7) id AA00752; Mon, 4 Feb 85 00:29:49 est
Date: Mon, 4 Feb 85 00:29:49 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8502040529.AA00752@unc>
To: Scheme@mit-mc.ARPA
Subject: Chez Scheme

=>                      Chez Scheme

     Chez Scheme is an implementation of Scheme for Vaxes
running 4.2 Bsd Unix.  Chez Scheme supports all required and
most optional features of the anticipated Scheme standard.
The first Chez Scheme release will include an extensive
reference manual.  A Chez Scheme tutorial is in preparation
for later releases.

Features of Scheme:

o    Clean, concise dialect of Lisp
o    Lexically scoped (as is Common Lisp)
o    Full function closures (first-class, full funarg)
o    Tail-recursion reliably translated into iteration
o    Full upward/downward continuations

Features of Chez Scheme:

o    Incremental native-code (Vax object code) compiler
o    Flexible user interface
o    Fast-loading compiled files
o    Very fast arbitrary precision integer and rational
     arithmetic
o    Programmable exception handlers
o    Support for multi-tasking (timer interrupts,
     continuations)
o    String and vector operations
o    Macros and structures
o    Engines (a process abstraction)

     Application programs distributed with the first release
of Chez Scheme include a set operation package, a logic
programming subsystem, a lazy-cons facility, and a generic
matrix, vector and scalar multiplication package.

     Faster than many Lisp systems, Chez Scheme may be the
fastest Scheme available.  On the Vax 11/780, Chez Scheme is
competitive with benchmarks reported for Franz Lisp and
Digital Common Lisp at last summer's AAAI conference in
Austin, TX.  For example, Chez Scheme runs the "Tak"
benchmark in 3.4 cpu seconds and the "Deriv" benchmark in
21.9 cpu seconds.  The code tested contained no
declarations, used generic arithmetic, and had no inlined
calls.  No separate compilation phase is necessary: all code
loaded into Chez Scheme is compiled incrementally.

     Chez Scheme is available for mid-March distribution to
US educational institutions only.  We will send a license
agreement to interested parties.  There is a $400
distribution fee.  We are not yet able to do foreign or
commercial distributions, but contact us if you are
interested.

     Write for a copy of the license agreement and ordering
information to:

     R. Kent Dybvig
     Department of Computer Science
     New West Hall (035-A)
     University of North Carolina
     Chapel Hill, NC  27514
     USA

     decvax!mcnc!unc!dyb    (usenet)
     dyb.unc@Csnet-Relay    (ARPANET)

∂05-Feb-85  1002	JAR@MIT-MC 	string->symbol, symbol->string   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 5 Feb 85  10:02:15 PST
Date: 5 February 1985 13:03-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  string->symbol, symbol->string
To: dyb%unc.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of Sun 3 Feb 85 12:00:27 est from Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

    Date: Sun, 3 Feb 85 12:00:27 est
    From: Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

    "symbol->string" and "string->symbol functions are not analogous to
    "list->string" or "string->list".

    "list->string" converts the same data from one representation into
    another, with no loss of information.  The same is true for "string->list",
    "list->vector", "vector->list" and "character->integer".  

There definitely is loss of information in list->vector and friends; you
lose eq-ness and location identity.  (vector->list (list->vector l))
gives a copy of the list, so rplacas and rplacds will affect different
cells.

    A symbol is more than just an alternate representation for a string.
    It can be an identifier or keyword.  Some implementations allow symbols
    to have property lists.  All of this information is lost in the conversion
    from symbol to string, some is regained in the opposite conversion.
    I tend to think of the name of a symbol as an attribute of that symbol.
    "symbol->string" is more correctly called "symbol-name".

How do symbols differ from numbers, which can also be identifiers or
"keywords," in this regard?  The way I look at things, all associations
of information with symbols are through tables not intimately tied to
the symbol itself.  To say that symbols "have" values is like saying
that integers "have" values - getting a value out of an environment,
given a symbol, is completely analogous to getting a value out of a
vector, given an integer.  "Essential scheme" intentionally doesn't have
property lists.  Symbol eq-ness is global, so property lists would
violate the desire (based on modularity considerations) to avoid global
state; and given reasonable association tables, they are unnecessary.

    Furthermore, whereas one can expect "string->list" to return a new list
    made up of unique cons-cells, "string->symbol" may return an existing
    symbol.  The name "intern" is more appropriate for this functionality.
    (Perhaps "hash-make-symbol" would be a better name.)

But character->integer (or char->ascii or whatever you want to call it)
may return an existing integer.  What is the difference?  Since symbols
are immutable objects, like numbers, it's okay that an existing one is
returned.

Reference to hashing doesn't seem very abstract to me...

    If making a unique, uninterned symbol is supported, the name "make-symbol"
    is appropriate.  

I personally don't believe in uninterned symbols (yet?), but if they
existed then make-symbol would be an okay name, maybe better than
string->uninterned-symbol, but I don't much care.

I think that the "->" convention shouldn't have such a terribly strict
meaning.  I guess it's my feeling that string->symbol and symbol->string
are acceptable even if they aren't strictly analogous to list->vector
and vector->list.

Jonathan Rees (JAR@MC)

∂05-Feb-85  1007	JAR@MIT-MC 	Scheme String Operations    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 5 Feb 85  10:06:52 PST
Date: 5 February 1985 13:08-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  Scheme String Operations
To: SCHEME @ MIT-MC
In-reply-to: Msg of Sun 3 Feb 85 11:59:27 est from Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

I should point out that there were people at the workshop who felt
strongly that strings should not be mutable.  I don't much care one way
or the other.  If the things which use the "..." syntax are immutable
then there ought to be such a thing as vector-of-character; also, if
strings are immutable then it's not clear how they are different from
symbols (maybe just that they self-evaluate).  But those of you who
strongly think (or thought) that strings should be immutable should
speak up.

Jonathan

∂21-Feb-85  1259	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Draft delayed to 15 March    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Feb 85  12:59:45 PST
Received: from indiana by csnet-relay.csnet id ad22218; 21 Feb 85 15:20 EST
Date: Thu, 21 Feb 85 13:14:25 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA04423; Thu, 21 Feb 85 13:14:25 est
To: scheme@mit-mc.ARPA
Subject: Draft delayed to 15 March

The draft of the final report on the Brandeis workshop, which was to have
come out around 1 March, will be delayed to the vicinity of 15 March.
I will be travelling until 4 March and probably won't be able to finish
the draft until I get back.  I am sorry for the delay.

				William Clinger
				Indiana University


∂10-Mar-85  1716	@MIT-MC:GJS@MIT-EECS 	Numbers Committee Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 10 Mar 85  17:16:24 PST
Received: from MIT-EECS by MIT-MC via Chaosnet; 10 MAR 85  16:53:21 EST
Date: Sun 10 Mar 85 16:53:46-EST
From: GJS%MIT-EECS@MIT-MC.ARPA
Subject: Numbers Committee Report
To: scheme@MIT-MC



Sorry it took so long, but I was afraid to do a half-assed job.  The following
report raises 10↑10 issues which should be thought about by all of us.  I 
believe (after a bit of study) that other language people have been 
inadequately careful about the status of numbers in their languages.  Numbers
are probably the most complicated data structures we ever deal with, so we must
try to do a good job on them.

The report is entirely the responsibility of GJS (so throw stones at him), 
though Bill Rozas, Jon Rees, Guy Steele, Chris Hanson, Hal Abelson, Yekta
Gursel, and Chris Lindblad have made significant contributions -- most of
their stones have been thrown and absorbed (some hurt!).


                            Scheme Numbers


Intent

    Numerical computation has traditionally been neglected by the Lisp
community.  Until Common Lisp there has been no carefully thought out
strategy for organizing numerical computation; and with the exception
of the MacLisp system there has been little effort to efficiently
execute numerical code.  We applaud the excellent work of the Common
Lisp committee and we accept many of their recommendations.  In some
ways we simplify and generalize their proposals in a manner consistent
with the purposes of Scheme.

Scheme numerical operations treat numbers as abstract data, as
independent of the machine representation as is possible.  Thus, the
casual user should be able to write simple programs without having to
know that the implementation may use fixed-point, floating-point, and
perhaps other representations for his data.  Unfortunately, this
illusion of uniformity can only be sustained approximately -- the
implementation of numbers will leak out of our abstraction whenever
the user must be in control of precision, or accuracy, or when he must
construct especially efficient computations.  Thus we also must
provide escape mechanisms so that a sophisticated programmer can
exercise more control of the execution of his code and the
representation of his data when it is essential to do so.

We separate out several apparently related issues of representation --
the abstract numbers, their machine representation, and the
input/output formats of the symbolic expressions which denote
numerical constants.  We will use mathematical words such as NUMBER,
COMPLEX, REAL, RATIONAL, and INTEGER for properties of the abstract
numbers, data-structure names such as FIXNUM, BIGNUM, RATNUM, and
FLONUM for machine representations, and names like INT, FIX, FLO, SCI,
RAT, POLAR, and RECT for input/output formats.


Numbers

    A Scheme system provides data of type NUMBER, which is the most
general numerical type supported by that system.  NUMBER is likely to
be a complicated union type implemented in terms of FIXNUMs, BIGNUMS,
FLONUMS, etc. but this should not be apparent to a naive user.  What
the user sees is that the obvious operations on numbers produce the
mathematically expected results, within the limits of the
implementation.  Thus if the user divides 3 by 2, he should get
something like 1.5 (or, the exact fraction 3/2).  If he adds that
result to itself, and if the implementation can swing it, he should
get an exact 3.
!
Mathematically, numbers may be arranged into a tower of subtypes with
natural projections and injections relating adjacent members of the
tower:

                                NUMBER
                                COMPLEX
                                REAL
                                RATIONAL
                                INTEGER

We impose a uniform rule of downward coercion -- a number of one type
is also of a lower type if the injection (up) of the projection (down)
of a number leaves the number unchanged.  Since this tower is a real
mathematical entity, Scheme provides predicates and procedures that
access the tower.

Not all Scheme implementations must provide the whole tower, but they
are required to implement a coherent subset, consistent with the
purposes of Scheme.


Exactness

    Numbers are either EXACT or INEXACT.  A number is exact if it was
derived from EXACT numbers using only EXACT operations.  A number is
INEXACT if it models a quantity known only approximately, if it was
derived using INEXACT ingredients, or if it was derived using INEXACT
operations.  Thus INEXACTness is a contagious property of a number.
Some operations, such as the square root (of non-square numbers) must
be INEXACT because of the finite precision of our representations.
Other operations are inexact because of implementation requirements.
We emphasize that exactness is independent of the position of the
number on the tower.  It is perfectly possible to have an INEXACT
INTEGER or an EXACT REAL; 355/113 may be an EXACT RATIONAL or it may
be an INEXACT RATIONAL approximation to pi, depending on the
application.

Operationally, it is the system's responsibility to combine EXACT
numbers using exact methods, such as infinite precision integer and
rational arithmetic, where possible.  An implementation may not be
able to do this (if it does not use infinite precision integers and
rationals), but if a number becomes inexact for implementation reasons
there is probably an important error condition, such as integer
overflow, to be reported.  Arithmetic on INEXACT numbers is not so
constrained.  The system may use floating point and other flaky
representation strategies for INEXACT numbers.  This is not to say
that implementors need not use the best known algorithms for INEXACT
computations -- only that high-quality approximate methods are
allowed.  In a system which cannot explicitly distinguish exact from inexact numbers the system must do its best to
maintain precision.  Scheme systems must not burden users with
numerical operations described in terms of hardware and
operating-system dependent representations such as FIXNUM and FLONUM.
These representation issues should not be germane to the user's
problems.
!
We highly recommend that the IEEE 32-bit and 64-bit floating-point
standards be adopted for implementations that use floating-point
internal representations.  To minimize loss of precision we adopt the
following rules: If an implementation uses several different size
floating-point formats, the results of any operation with a
floating-point result must be expressed in the largest format used to
express any of the floating-point arguments to that operation.  It is
desirable (but not required) for potentially irrational operations
such as SQRT, when applied to EXACT arguments, to produce EXACT
answers when that is possible (eg.  sqrt[4]=2, exactly).  If an EXACT
number (or an INEXACT number represented as a FIXNUM, a BIGNUM, or a
RATNUM) is operated upon so as to produce an INEXACT result (as by
SQRT), then if the result is represented as a FLONUM, then the largest
available format FLONUM must be used; but if the result is expressed
as a RATNUM then the rational approximation must have at least as much
precision as the largest available format FLONUM.  (Note that this
last rule is much stronger than that used in Common Lisp.  Consider
the result of the square root of a rational, for example.)


Numerical Operations

    Scheme provides the usual set of operations for manipulation of
numbers.  In the specification below we illustrate each built in
numerical operation with an expression using the default operator
symbol which is bound to that operation in the global environment.  In
general, numerical operations require numerical arguments.  We use the
following symbols to represent the various types of object in our
descriptions.  It is an error for an operation to be presented with an
argument that it is not specified to handle.

obj				any arbitrary object
z, z1, ... zi, ...		{complex, real, rational, integer} x,
x1, ... xi, ...		{real, rational, integer}
q, q1, ... qi, ...		{rational, integer} n, n1, ... ni, ...
{integer}

In our descriptions some arguments are required and others are
optionally allowed.  For example, numerical comparisons are allowed to
have any number of arguments, but they must have at least two.  We
indicate this by putting in explicit argument symbols for each
required argument and a "..." indicating the rest.
!
A.  Numerical type predicates can be applied to any kind of argument.
They return true if the object is of the named type.  In general, if a
type predicate is true of a number then all higher type predicates are
also true of that number.  Not every system supports all of these
types.  It is entirely possible to have a Scheme system which only has
INTEGERs, however, it must have all of these predicates.

(NUMBER? obj) (COMPLEX? obj) (REAL? obj) (RATIONAL? obj) (INTEGER?
obj)


B.  Numerical predicates test a number for a particular property.
They return a boolean value.

(ZERO? z) (POSITIVE? x) (NEGATIVE? x) (ODD? n) (EVEN? n)

(EXACT? z) (INEXACT? z)


C.  Numerical comparisons require all of their arguments to be
numbers.  They optionally take many arguments, as in Common Lisp, to
facilitate encoding of range checks.  Not all implementations support
this extension.  These predicates have redundant names (with and
without the terminal "?") to make all populations happy.  Warning: On
INEXACT numbers equality tests will give unreliable results; other
numerical comparisons are only heuristically useful (ask a numerical
analyst about this!)

(= z1 z2 ... zi)          all arguments are numerically equal
(=? z1 z2 ... zi)            

(< x1 x2 ... xi)          arguments are monotonically increasing
(<? x1 x2 ... xi)

(> x1 x2 ... xi)          arguments are monotonically decreasing
(>? x1 x2 ... xi)

(<= x1 x2 ... xi)         arguments are monotonically nondecreasing
(<=? x1 x2 ... xi)

(>= x1 x2 ... xi)         arguments are monotonically nonincreasing
(>=? x1 x2 ... xi)


(max x1 ... xi)
(min x1 ... xi)
!
D. Arithmetic operations require all arguments to be numbers.
Generalization to arbitrary numbers of arguments is implementation
dependent.

(+ z1 ... zi)            ==> z1 + ... + zi
   (+ z)                    ==> z
   (+)                      ==> 0     (the identity)

(* z1 ... zi)            ==> z1 * ... * zi
   (* z)                    ==> z
   (*)                      ==> 1     (the identity)

(- z1 ... zi)            ==> z1 - z2 - ... - zi
   (- z)                    ==> -n

(/ z1 ... zi)            ==> z1 / z2 / ... / zi
   (/ z)                    ==> 1/z

(-1+ z)                  ==> -1 + z
(1+ z)                   ==> 1 + z

(abs z)


E.  Integer division operations are only defined on integers.

(quotient n1 n2)           ==> n3
(remainder n1 n2)          ==> n4

(modulo n1 n2)             ==> n4

In general, these are intended to implement number-theoretic division,
where for positive arguments, n1 and n2

                   n1 = n3*n2 + n4 and 0 <= n4 < d.

REMAINDER and MODULO differ on negative arguments as in the Common
Lisp REM and MOD procedures -- the remainder always has the sign of
the dividend, the modulo always has the sign of the divisor:

(modulo 13 4)   ==>  1         (remainder 13 4)   ==>  1
(modulo -13 4)  ==>  3         (remainder -13 4)  ==> -1
(modulo 13 -4)  ==> -3         (remainder 13 -4)  ==>  1
(modulo -13 -4) ==> -1         (remainder -13 -4) ==> -1


F.  The following procedures are also only defined on integers.  The
result is always non-negative.

(gcd n1 ... ni)              Greatest common divisor
			       (gcd) ==> 0     (the identity)

(lcm n1 ... ni)              Least common multiple
			       (lcm) ==> 1     (the identity)
!
G.  Integers and rationals can be made using the following procedures.
Note, this does not make the answer EXACT -- in fact, the resulting
number is clearly INEXACT, it can be made EXACT with an exactness
coercion.

(floor x)     The largest integer not larger than x
(ceiling x)   The smallest integer not smaller than x
(truncate x)  The integer of maximal absolute value not larger than x
(round x)     The closest integer to n.  Rounds to even when halfway.

(rationalize x y)     Produces the best rational approximation to x 
                       within the tolerance specified by y.
   (rationalize x)    Produces the best rational approximation to x,
                       preserving all of the precision in its 
                       representation.

H.  In implementations which support real numbers the following are
defined to conform with the Common Lisp standard as to meaning (be
careful of the branch cuts if complex numbers are allowed).

(exp z) (log z)   (expt z1 z2) (sqrt z)

(sin z) (cos z) (tan z)   (asin z) (acos z) (atan z1 z2)           


I.  In implementations which support complex numbers we also provide

(make-rectangular x1 x2)      ==> x1 + x2i
(make-polar x3 x4)            ==> x3*e↑x4i

(real-part z) (imag-part z)   (magnitude z) (angle z)


J.  Exactness coercions.

(exact->inexact z)         Makes an inexact representation of z.
                              Pretty harmless.
(inexact->exact z)         Makes an exact representation of z.
                              I hope you know what you are doing here!


K.  Type-restricted operations are useful for error checking, or as
advice to a compiler.  Scheme optionally supplies such type-restricted
operations: If op is defined on objects of numerical type, t1, and if
t2 is any type lower on the tower than t1, then (t2 op) is the
restricted operator for objects of type t2.  For example, the
following are expressions using restricted operators:

((real sqrt) 5)		; Gets the right thing.
((real sqrt) -1)	; Will signal an error.
((integer sqrt) 10)	; Will signal an error -- You probably 
                           wanted to compute (truncate ((real sqrt) 10))
!
For completeness, the system also supplies the most general operations

((number +) 3 4) 

The default operations, initially bound to the customary operators in
the global environment, are these most general operations.  The
type-restriction procedures REAL, INTEGER, ... are simple maps which
map the default operations to their restricted cousins.

Some systems may want to enhance this facility, to allow integer
subranges or other mathematically meaningful restrictions such as
modular arithmetic, for example:

(((integer-subrange 3 5) +) 2 3 4)   ;Will signal an error.


Numerical Input and Output

    Scheme allows all of the traditional ways of expressing numerical
constants, though only some may be supported by any particular
implementation.  These expressions are intended to be purely
notational; any kind of number may be expressed in any form that the
user deems convenient.  Of course, expressing 1/7 as a
limited-precision decimal fraction will not exactly express the
number, but this approximate expression may be just what the user
wants to see.

The expressions of numerical constants can be specified using formats.
The system provides a procedure, NUMBER->STRING, which takes a number
and a format and which produces a string which is the printed
expression of the given number in the given format.

(number->string <number> <format>)   ==>  <string>

This procedure will mostly be used by sophisticated users and in
system programs.  In general, a naive user will need to know nothing
about the formats because the system printer will have reasonable
default formats for all types of NUMBERs.  The system reader will
construct reasonable default numerical types for numbers expressed in
each of the formats it recognizes.  If a user needs control of the
coercion from strings to numbers he will use STRING->NUMBER, which
takes a string, an exactness, and a radix and which produces a number
of the maximally precise applicable type expressed by the given
string.

(string->number <string> E|I B|O|D|X)  ==>  <number>
!
Formats may have parameters.  For example, the "(SCI 5 2)" format
specifies that a number is to be expressed in FORTRAN scientific
format with 5 significant places and two places after the radix point.

The following are all numerical constant expressions.  The comment
shows the format that was used to produce the expression:

123  +123  -123                    ; (INT) format
12345678901234567890123456789      ; A big one
355/113  -355/113  +355/113	   ; (RAT) format
+123.45  -123.45                   ; (FIX 2) format
3.14159265358979		   ; (FIX 14) format
3.14159265358979                   ; (FLO 15) format
123.450                            ; (FLO 6) format
-123.45E-1                         ; (SCI 5 2) format
123E3  123E-3  -123E-3             ; (SCI 3 0) format
-1+2i                              ; (RECT (INT) (INT)) format
1.2@1.570796                       ; (POLAR (FIX 1) (FLO 7)) format

A numerical constant may be specified with an explicit radix by a
prefix.  The prefixes are: #B (binary), #O (octal), #D (decimal), #X
(hex).  A format may specify that a number be expressed in a
particular radix.  The radix prefix may be suppressed.  For example,
one may express a complex number in polar form with the magnitude in
octal and the angle in decimal as follows:

#o1.2@#d1.570796327  ;(POLAR (FLO 2 (RADIX O)) (FLO (RADIX D))) format
#o1.2@1.570796327    ;(POLAR (FLO 2 (RADIX O)) (FLO (RADIX D S)) format

A numerical constant may be specified to be either EXACT or INEXACT by
a prefix.  The prefixes are: #I (inexact), #E (exact).  An exactness
prefix may appear before or after any radix prefix that is used.  A
format may specify that a number be expressed with an explicit
exactness prefix, or it may force the exactness to be suppressed.  For
example, the following are ways to output an inexact value for pi:

#I355/113           ; (RAT (EXACTNESS))
355/113             ; (RAT (EXACTNESS S))
#I3.1416            ; (FIX 4 (EXACTNESS))

An attempt to produce more digits than are available in the internal
machine representation of a number will be marked with a "#" filling
the extra digits.  This is not a statement that the implementation
knows or keeps track of the significance of a number, just that the
machine will flag attempts to produce 20 digits of a number which has
only 15 digits of machine representation:

3.14158265358979#####       ; (FLO 20 (EXACTNESS S))

In systems with both single and double precision FLONUMs one may want
to specify which size we want to use to internally represent a
constant.  For example, we may want a constant whidh is pi rounded to
!
the single precision length, or we might want a long number which has
the value 6/10.  In either case, we are specifying an explicit way to
represent an INEXACT number.  For this purpose, we allow one to
express a number with a prefix which indicates short or long FLONUM
representation:

#S3.14159265358979          ; Round to short -- 3.141593
#L.6                        ; Extend to long -- .600000000000000



Details of formats

    The format of a number is notated as a list beginning with a
format descriptor, such as SCI.  Following the descriptor are
parameters used by that descriptor, such as the number of significant
digits to be used.  Parameters which are omitted are defaulted.  Next,
one may specify modifiers, such as RADIX or EXACTNESS, which
themselves may be parameterized.  The format descriptors are:

(INT)
   Express as an integer.  The radix point is implicit.  If there are
   not enough significant places, as in trying to express 6.0238E23
   (internally represented as a 7 digit FLONUM) as an integer we would
   get "6023800################".

(RAT n)
   Express as a rational fraction.  n specifies the largest
   denominator to be used in constructing a rational approximation to
   the number being expressed.  If n is omitted it defaults to
   infinity. 

(FIX n)
   Express with a fixed radix point.  n specifies the number of
   places to right of the radix point.  n defaults to the size of a
   single-precision FLONUM.  If there are not enough significant
   places, as in trying to express 6.0238E23 (internally represented
   as a 7 digit FLONUM) as a (FIX 2) we would get
   "6023800################.##".

(FLO n) 
   Express with a floating radix point.  n specifies the total number
   of places to be displayed.  n defaults to the size of a single-
   precision FLONUM.  If the number is out of range, it is converted
   to (SCI).  (FLO H) allows the system to heuristically express a FLO
   for human consumption (as in MacLisp printer).
!
(SCI n m)
   Express in exponential notation.  n specifies the total number of
   places to be displayed.  n defaults to the size of a single-
   precision FLONUM.  m specifies the number of places to the right of
   the radix point.  m defaults to n-1.  (SCI H) does heuristic
   expression. 

(RECT r i)
   Express as a rectangular form complex number.  r and i are formats
   for the real and imaginary parts respectively.  They default to
   (HEUR).

(POLAR m a)
   Express as a polar form complex number.  m and a are formats for
   the magnitude and angle respectively.  m and a default to (HEUR).

(HEUR)
   Express heuristically, as in the MacLisp printer (see Steele),
   using the minimum number of digits required to get an expression
   which when coerced back to a number produces the original machine
   representation.  EXACT numbers are expressed as (INT) or (RAT).
   INEXACT numbers are expressed as (FLO H) or (SCI H) depending on
   their range.  Complex numbers are expressed in (RECT).  This is the
   normal default of the system printer.


The following modifiers may be added to a numerical format
specification:

(EXACTNESS s)
   This controls the expression of the exactness label of a number.  s
   indicates whether the exactness is to be E (expressed) or S
   (suppressed).  s defaults to E.  If no exactness modifier is
   specified for a format the exactness is by default not expressed.

(RADIX r s)
   This forces a number to be expressed in the radix r.  r may be B
   (binary), O (octal), D (decimal), or X (hex).  s indicates whether
   the radix label is to be E (expressed) or S (suppressed).  s
   defaults to E.  If no radix modifier is specified the default is 
   decimal and the label is suppressed.
	
-------

∂11-Mar-85  2110	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	I/O proposal  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 11 Mar 85  21:09:47 PST
Received: from csnet-relay by MIT-MC.ARPA; 11 MAR 85 23:49:17 EST
Received: from indiana by csnet-relay.csnet id ac04021; 11 Mar 85 23:37 EST
Date: Mon, 11 Mar 85 23:20:31 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA14898; Mon, 11 Mar 85 23:20:31 est
To: scheme@mit-mc.ARPA
Subject: I/O proposal

From Gary Brooks and William Clinger at Indiana U:

This is an interim proposal.  It takes an old-fashioned view of
streams, and it does nothing about windows and graphics.  Arguments to 
functions are delimited by angle brackets (<...>) and optional arguments
are further delmited by curly brackets ({...}).



(eof? <object>)                                         Essential

   EOF? takes an object and returns true if the object is an end of
   file object.  The precise set of end of file objects will vary
   among implementations, but in any case no end of file object will
   ever be a character or an object that can be read in using READ.

   Rationale:
   A fixed set of end of file objects seems to be simpler than
   allowing each input procedure to take yet another optional
   argument specifying what to do on end of file.  Allowing for a
   set of such objects rather than a single such object allows for
   different implementation strategies.


(read {<stream>})                                               Essential

   READ takes an input stream as argument and returns the next
   object parsable from the stream, updating the stream to point to
   the first character past the end of the written representation of
   the object.  If an end of file is encountered in the input before
   any characters are found that can begin an object, then an end of
   file object is returned.  If an end of file is encountered after
   the beginning of an object's written representation, but the
   written representation is incomplete and therefore not parsable,
   an error must be signalled.  The stream argument to READ may be
   omitted, in which case it defaults to (CURRENT-INPUT-STREAM).

   Rationale:
   READ corresponds to Common Lisp's READ-PRESERVING-WHITESPACE.
   This will require something like UNREAD-CHAR or PEEK-CHAR
   internally.  For simplicity, it is never an error to encounter
   end of file when READ is called.


(write <object> {<stream>})                             Essential

   WRITE takes an object and an output stream and writes a
   representation of the object to the stream.  Strings that appear
   in the written representation are enclosed in double quotes, and
   within those strings backslash and double quote characters are
   escaped by backslashes.  (Implementations that allow
   slashification within symbols will probably want WRITE to
   slashify funny characters in symbols as well.)  WRITE returns an
   unspecified value. The stream argument to WRITE may be omitted,
   in which case it defaults to (CURRENT-OUTPUT-STREAM).


(display <object> {<stream>})                           Essential

   DISPLAY takes an object and an output stream and writes a
   representation of the object to the stream.  Strings that appear
   in the written representation are not enclosed in double quotes,
   and no characters are escaped within those strings.  DISPLAY
   returns an unspecified value.  The stream argument to DISPLAY may
   be omitted, in which case it defaults to (CURRENT-OUTPUT-STREAM).
   
   Rationale:
   WRITE is for producing machine-readable output, DISPLAY for
   producing human-readable output.
   
(newline {<stream>})                                    Essential

   NEWLINE takes an output stream and writes a newline to the
   stream.  NEWLINE returns an unspecified value.  The stream
   argument to NEWLINE may be omitted, in which case it defaults to
   (CURRENT-OUTPUT-STREAM).
   
   Rationale:
   NEWLINE abstracts away from the implementation details of
   ending a line (or is it starting a new one?).

(listen? {<stream>})                                    Optional

   LISTEN? takes an input stream (an interactive stream in the
   useful case) and returns true if a character is ready on that
   stream so that a READ-CHAR operation will not hang and returns
   false if a READ-CHAR operation will hang.  If the stream is at
   end of file then the value returned by LISTEN? is unspecified.
   
   Rationale:
   LISTEN? is needed for interactive input streams.

(read-char {<stream>})                                  Essential

   READ-CHAR takes an input stream and returns the next character
   available from the stream, updating the stream to point to the
   following character.  If no more characters are available from
   the stream, an end of file value is returned.  The stream
   argument to READ-CHAR may be omitted, in which case it defaults
   to (CURRENT-INPUT-STREAM).
   
(display-char <character> {<stream>})                   Essential

   DISPLAY-CHAR takes a character and an output stream, and writes
   the character itself (not a written representation of the
   character) to the stream.  DISPLAY-CHAR returns an unspecified
   value. The stream argument to DISPLAY-CHAR may be omitted, in
   which case it defaults to (CURRENT-OUTPUT-STREAM).
   
   Rationale:   
   READ-CHAR and DISPLAY-CHAR are for low-level I/O.

(load <filename>)                                       Essential

   LOAD takes a string that names an existing file containing Scheme
   source code.  It reads Scheme expressions from the file and
   interprets them sequentially as though they had been typed
   interactively.  It is not specified whether the results of the
   expressions are printed.  Neither is it specified whether or not the
   LOAD procedure affects the values returned by (CURRENT-INPUT-STREAM)
   and (CURRENT-OUTPUT-STREAM) during the loading process.  LOAD returns
   an unspecified value.
   
   Rationale:
   For portability LOAD must operate on source files.  Its operation
   on other kinds of files necessarily varies among implementations.
   
(transcript-on <file-name>)                             Optional

   TRANSCRIPT-ON takes a string that names an output file to be
   created, and returns an unspecified value.  The effect of
   TRANSCRIPT-ON is to open the named file for output, and to cause
   a transcript of subsequent interaction between the user and the
   Scheme system to be written to the file.  The transcript is ended
   by a call to TRANSCRIPT-OFF.  Only one transcript may be in
   progress at any time.  (Some implementations may relax this
   restriction.)

(transcript-off)                                        Optional

   TRANSCRIPT-OFF takes no arguments and returns an unspecified
   value.  It ends any transcript in progress and closes the
   transcript file.
   
   Rationale:
   TRANSCRIPT-ON and TRANSCRIPT-OFF are redundant in some systems,
   but systems that need them should provide them.

(stream? <object>)                                      Essential

   STREAM? takes one argument and returns true iff its argument is a
   stream.
   
   Rationale:
   Perhaps STREAM? should be subdivided into INPUT-STREAM? and
   OUTPUT-STREAM?.

(current-input-stream)                                  Essential

   CURRENT-INPUT-STREAM takes no arguments and returns the current
   default input stream.

(current-output-stream)                                 Essential

   CURRENT-OUTPUT-STREAM takes no arguments and returns the current
   default output stream.
   
   Rationale:
   CURRENT-INPUT-STREAM and CURRENT-OUTPUT-STREAM are procedures
   rather than variables to allow for various ways to implement the
   default streams.  Explicit fetching of the default streams is
   convenient for programs that want to change the default stream
   using WITH-INPUT-FROM-FILE or WITH-OUTPUT-TO-FILE and still use
   the original default stream for some I/O; see below.
   
(call-with-input-file <string> <procedure>)             Essential

   CALL-WITH-INPUT-FILE takes a procedure of one argument and a 
   string naming an existing file and calls the procedure with the
   stream obtained by opening the named file for input.  If the
   file cannot be opened, an error should be signalled. If the
   procedure returns, then the stream is closed automatically and
   the value yielded by the procedure is returned by
   CALL-WITH-INPUT-FILE. If the current continuation ever changes in
   such a way as to make it doubtful that the procedure will return,
   CALL-WITH-INPUT-FILE may close the input stream.  The exact
   interaction of escape procedures with CALL-WITH-INPUT-FILE is
   unspecified.
   
(call-with-output-file <file-name> <procedure>)         Essential

   CALL-WITH-OUTPUT-FILE takes a procedure of one argument and a string
   naming a file to be created and calls the procedure with the stream
   obtained by opening the named file for output.  If the file cannot be
   be opened, an error should be signalled. If a file with that name
   already exists, the effect is unspecified. If the procedure returns,
   then the stream is closed automatically and the value yielded by the
   procedure is returned by CALL-WITH-OUTPUT-FILE. If the current
   continuation ever changes in such a way as to make it doubtful that
   the procedure will return, CALL-WITH-OUTPUT-FILE may close the output
   stream.  The exact interaction of escape procedures with
   CALL-WITH-OUTPUT-FILE is unspecified.  

   Rationale:
   CALL-WITH-INPUT-FILE and CALL-WITH-OUTPUT-FILE are convenient for
   programs that need to read input from or send output to several
   directions at once. They cannot be synthesized from
   WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE so they are the essential
   procedures.  Whether or not they close files when there is a throw out
   of the procedure is mainly a performance issue, of greatest importance
   when there is a small limit on the number of files that can be open at
   once.  If they close files for a throw, then the vagueness of what it
   means for the current continuation to change in such a way as to make
   it doubtful that a procedure will return, the possibility of a throw
   back in, and the vagueness of what it means to close a file, make it
   unwise to specify the exact interaction of the file-closing mechanism
   with escape procedures.

   It is arguable whether the notion of closing a file should be
   reflected in the semantics of Scheme.  Operating systems require
   that files be closed for the following reasons:
   
       1.  To reclaim storage.  This should be left to the garbage
       collector.
   
       2.  To prevent some table in the operating system from
       overflowing because there are too many files open at once.
       Only implementations that have this problem should have to
       worry about it.
   
       3.  To facilitate file locking.  This seems to be the only
       semantic reason for closing a file, and even so there are
       implementations for which it isn't meaningful.
   
   Because some systems have to worry about closing files, however,
   all portable Scheme code must worry about it.  We have tried to
   follow MIT's lead in isolating the worry within a few standard
   procedures.
   
   
(open-input-file <file-name>)                           Optional

   OPEN-INPUT-FILE takes a string naming an existing file and
   returns an input stream capable of delivering characters from the
   file.  If the file cannot be opened, an error should be signalled.

(open-output-file <file-name>)                          Optional

   OPEN-OUTPUT-FILE takes a string naming an output file to be
   created and returns an output stream capable of writing
   characters to a new file by that name.  If the file cannot be
   opened, an error should be signalled.  If a file with the given
   name already exists, the effect is unspecified.
   
(close-input-stream <stream>)                           Optional

   CLOSE-INPUT-STREAM takes an input stream and returns an
   unspecified value.  If the stream is connected to a file, the
   file is closed and the stream rendered incapable of delivering
   characters.

(close-output-stream <stream>)                          Optional

   CLOSE-OUTPUT-STREAM takes an output stream and returns an
   unspecified value.  If the stream is connected to a file, the
   file is closed and the stream rendered incapable of writing
   characters to it.

   Rationale:
   OPEN-INPUT-FILE, OPEN-OUTPUT-FILE, CLOSE-INPUT-STREAM, and
   CLOSE-OUTPUT-STREAM are needed to use streams whose lifetimes are
   not properly nested, which is to say they are seldom needed.
   OPEN-INPUT-FILE and OPEN-OUTPUT-FILE are distinct to avoid the
   need for a switch argument; if independent switches were
   required, it would be better to use switches rather than have a
   product space of procedures.  CLOSE-INPUT-STREAM and
   CLOSE-OUTPUT-STREAM could probably be combined into CLOSE-STREAM
   with no great loss.  A different set of procedures will
   be needed to create streams from and to strings, and the closing
   procedures should still work on them.  It seems that closing a
   string output stream should yield a string, but it isn't clear
   what should be returned when a file output stream is closed.

(with-input-from-file <file-name> <thunk>)              Optional

   WITH-INPUT-FROM-FILE takes a string and a thunk (a procedure of
   no arguments).  The string must name an existing file.  The file
   is opened for input, an input stream connected to it is made the
   default value returned by (CURRENT-INPUT-STREAM), and the thunk
   is invoked.  When the thunk returns, (CURRENT-INPUT-STREAM) is
   closed and the previous default value returned by
   (CURRENT-INPUT-STREAM) is restored. WITH-INPUT-FROM-FILE returns
   the value returned by the thunk. Furthermore WITH-INPUT-FROM-FILE
   should attempt to close the input stream and restore the default
   input stream whenever the current continuation changes in such a
   way as to make it doubtful that the thunk will ever return.

(with-output-to-file <file-name> <thunk>)               Optional

   WITH-OUTPUT-TO-FILE takes a stfung and a thunk.  The string names
   an output file to be created.  The file is opened for output, an
   output stream connected to it is made the default value returned
   by (CURRENT-OUTPUT-STREAM), and the thunk is invoked.  When the
   thunk returns, (CURRENT-OUTPUT-STREAM) is closed and the previous
   default value returned by (CURRENT-OUTPUT-STREAM) is restored.
   WITH-OUTPUT-FROM-FILE returns the value returned by the thunk.
   Furthermore WITH-OUTPUT-FROM-FILE should attempt to close the
   output stream and restore the default output stream whenever the
   current continuation changes in such a way as to make it doubtful
   that the thunk will ever return.
   
   It has been suggested that if evaluation of the thunk is
   abandoned and later continued then the file should be re-opened
   in exactly the same state that it had been in when it was last
   closed, but this may be awkward or inefficient in some
   implementations.
   
   Rationale:
   WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE are sufficient for
   programs that only use one input or one output at a time.  Indeed
   by nesting them and by fetching the various nested streams using
   CURRENT-INPUT-STREAM and CURRENT-OUTPUT-STREAM, arbitrarily many
   input or output files may be used.  The automatic closing of the
   streams may not be terribly important in some implementations,
   but the fact that the old defaults are restored is important
   semantically.  There are several incompatible ways that they
   could interact with escape procedures, however, and at this time
   it isn't entirely clear which ways are best.  See rationale for
   CALL-WITH-OUTPUT-FILE and CALL-WITH-INPUT-FILE.



∂12-Mar-85  0940	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Re: Numbers Committee Report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Mar 85  09:40:41 PST
Received: from csnet-relay by MIT-MC.ARPA; 12 MAR 85 12:39:35 EST
Received: from brandeis by csnet-relay.csnet id ac08006; 12 Mar 85 12:36 EST
Received: by brandeis.ARPA (4.12/4.7)
	id AA01743; Tue, 12 Mar 85 11:08:41 est
Date: 12 Mar 1985 10:57-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: Re: Numbers Committee Report
To: scheme@mit-mc.ARPA
Message-Id: <479491071/mw@brandeis>

Three comments (of #I10e10):

1.  (/ z1 ... zi) ==> ((z1 / z2) ... / zi)
-- since / is not associative, the order of operation should be
specified explicitly.  This is probably just an editing issue.

2. Are formats list structures or some other kind of object? That is
do you write

(let ((format (cons 'FLO '(13))))
     (number->string z format))

or is FLO some kind of functional object?  

3.  In paragraph K, are real, integer, etc supposed to be functions or
keywords?  That is, can you write

(let ((range real))
     ((range sqrt) x)) ?

In either case, this proposal ties up those identifiers in a pretty
complicated way.  I am not sure how bad this is, but it deserves
thought.

-- Mitch Wand



∂12-Mar-85  0954	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Re: I/O proposal
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Mar 85  09:54:14 PST
Received: from csnet-relay by MIT-MC.ARPA; 12 MAR 85 12:52:56 EST
Received: from brandeis by csnet-relay.csnet id ag08006; 12 Mar 85 12:39 EST
Received: by brandeis.ARPA (4.12/4.7)
	id AA02554; Tue, 12 Mar 85 12:08:14 est
Date: 12 Mar 1985 11:22-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: Re: I/O proposal
To: scheme@mit-mc.ARPA
Message-Id: <479492551/mw@brandeis>

A few remarks:

1.  LOAD does not specify how it interacts with CURRENT-INPUT-STREAM or
CURRENT-OUTPUT-STREAM while loading.  What is to be the preferred way
of loading a bootstrap of the following form:

(define! foo ...)

(define! bar (foo (read)))

..complicated data to be processed by foo during load..

It might be argued that this is bad style, but I am not convinced:
such a bootstrap is less dependent on operating system file naming
conventions than one with the data in a separate file.

2. "A different set of procedures will be needed to create streams from
and to strings, and the closing procedures should still work on them.
It seems that closing a string output stream should yield a string, but
it isn't clear what should be returned when a file output stream is
closed."

I don't understand this at all. The phrase "create streams from and to
strings" is rather difficult to parse, which doesn't help.

3. Are with-input-from-file and with-output-from-file the only way to
change the value of (current-input-stream) and (current-output-stream) ?
If so, shouldn't they be essential ?

-- Mitch Wand






∂12-Mar-85  1306	@MIT-MC:GJS@MIT-OZ 	Re: Numbers Committee Report  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Mar 85  13:04:10 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 12 MAR 85  16:03:00 EST
Date: Tue 12 Mar 85 16:02:43-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: Numbers Committee Report
To: mw%brandeis.csnet@CSNET-RELAY.ARPA
cc: scheme@mit-mc.ARPA
In-Reply-To: Message from "mw%brandeis.csnet@csnet-relay.arpa" of Tue 12 Mar 85 10:57:00-EST


Three comments (of #I10e10):

***** I certainly hope there are fewer than that!


1.  (/ z1 ... zi) ==> ((z1 / z2) ... / zi)
-- since / is not associative, the order of operation should be
specified explicitly.  This is probably just an editing issue.

***** I agree and I have already fixed that.


2. Are formats list structures or some other kind of object? That is
do you write

(let ((format (cons 'FLO '(13))))
     (number->string z format))

or is FLO some kind of functional object?  

***** My initial response is that formats are simple list structures -- 
      there may be some format interpreter, but it should not be part of 
      Scheme.  Presumably this can be later generalized and simplified, if
      someone wants to go through the trouble, but I would be happy with
      the dumb idea.


3.  In paragraph K, are real, integer, etc supposed to be functions or
keywords?  That is, can you write

(let ((range real))
     ((range sqrt) x)) ?

In either case, this proposal ties up those identifiers in a pretty
complicated way.  I am not sure how bad this is, but it deserves
thought.

***** The type-restriction operations are intended to be scheme procedures
      which take procedures as arguments and which produce procedures as
      values.  They are bound in the initial environment to the operator
      symbols REAL, INTEGER, etc.  They may be passed as arguments, etc.
      Thus, this does not tie up the identifiers at all, and the example
      you give shows that.
-------

∂12-Mar-85  1441	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Mar 85  14:41:18 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 12 MAR 85  17:39:56 EST
Date: Tue, 12 Mar 1985  17:25 EST
Message-ID: <CPH.12094520544.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Will Clinger <willc%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: I/O proposal
In-reply-to: Msg of 11 Mar 1985  23:20-EST from Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

The I/O proposal seems quite good!  In fact it is nearly identical to
the current MIT Scheme I/O system, which makes me happy.

I wonder why you chose the name "DISPLAY-CHAR" rather than
"WRITE-CHAR"?  I prefer "WRITE-CHAR" because it has no connotations of
display terminals, or of being viewed by a human; it says, simply,
that the character was written down somewhere.

Also, I think that you should have both "STREAM?" and its components
"INPUT-STREAM?" and "OUTPUT-STREAM?", because it makes more
information available without really constraining the implementation
in any fundamental way.  Clearly bidirectional streams can satisfy
both predicates.

Chris Hanson

∂12-Mar-85  1552	@MIT-MC:GJS@MIT-OZ 	Re: I/O proposal    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Mar 85  15:52:35 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 12 MAR 85  18:51:29 EST
Date: Tue 12 Mar 85 18:51:01-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: I/O proposal
To: willc%indiana.csnet@CSNET-RELAY.ARPA
cc: scheme@mit-mc.ARPA
In-Reply-To: Message from "Will Clinger <willc%indiana.csnet@csnet-relay.arpa>" of Tue 12 Mar 85 00:12:50-EST


I think the I/O proposal is very nice.  The only objection I have is the
use of the word STREAM for the IO stuff.  My problem is that we used that
word all through chapter 3 of our book to mean the functional programming
idea of (potentially) infinite sequence.  It will be very painful to change
that.  I propose that the word be changed to one of CHANNEL, PIPE, PORT, TUBE,
or any other appropriate euphemism.  I believe that my use of the word STREAM
is consistent with that of other authors on functional programming.
-------

∂14-Mar-85  1024	JAR@MIT-MC 	interaction of LOAD and CURRENT-INPUT-STREAM    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Mar 85  10:24:15 PST
Date: 14 March 1985 13:23-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  interaction of LOAD and CURRENT-INPUT-STREAM
To: mw%brandeis.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC

    Date: 12 Mar 1985 11:22-EST
    From: mw%brandeis.csnet at csnet-relay.arpa

    1.  LOAD does not specify how it interacts with CURRENT-INPUT-STREAM or
    CURRENT-OUTPUT-STREAM while loading.  What is to be the preferred way
    of loading a bootstrap of the following form:

    (define! foo ...)

    (define! bar (foo (read)))

    ..complicated data to be processed by foo during load..

    It might be argued that this is bad style, but I am not convinced:
    such a bootstrap is less dependent on operating system file naming
    conventions than one with the data in a separate file.

I don't see any reason for LOAD and CURRENT-INPUT-STREAM to interact,
and I think it is much better for them not to.  If they don't interact
you have a much better invariants on each, e.g.: doing LOAD on a file is
the same as doing LOAD on a file consisting of the string "(begin "
appended to the file appended to the string ")".

What's wrong with writing

    (define! foo ...)

    (define! bar (foo '

      ..complicated data to be processed by foo during load..

    ))  ?

This way you don't need to do explicit I/O at all.

... And incidentally, I don't remember the rationale for having both
DEFINE! and DEFINE.  I understand why DEFINE shouldn't have hairy
syntax, but what does DEFINE! give you that the stripped-down DEFINE
doesn't?

Jonathan

∂14-Mar-85  1228	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: I/O proposal  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Mar 85  12:28:17 PST
Received: from csnet-relay by MIT-MC.ARPA; 14 MAR 85 15:27:14 EST
Received: from ti-csl by csnet-relay.csnet id a021223; 14 Mar 85 14:58 EST
Date: 14 Mar 1985 0952-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: I/O proposal
To: willc%indiana.csnet@csnet-relay.arpa, scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 12-Mar-85 1001-CST
Received: from csl60 by ti-csl; Thu, 14 Mar 85 11:04 CST

Will-- A few questions and remarks about your I/O proposal:

-- What happened to the names PRIN1 and PRINC?  Are your WRITE and DISPLAY
meant to be equivalent, respectively, to PRIN1 and PRINC?  As I understand
page 382 of the Common LISP (CL) book, your WRITE is not incompatible with
CL's.  Likewise, CL doesn't seem to have a DISPLAY.  However, I am bothered
by my intuition that DISPLAY should be a terminal-oriented operation.

   Bottom line: I vote to go with WRITE and DISPLAY, but the names PRIN1
and PRINC should be reserved as well (as optional aliases).  The PRINT
operation should also be optional, with the CL-compatible meaning we agreed
on at the workshop.

-- DISPLAY-CHAR seems to be a redundant, restricted form of DISPLAY. Since
DISPLAY is essential, DISPLAY-CHAR should be dropped.

-- The name LISTEN? also is slightly unintuitive to me; how about INPUT?,
or MORE-INPUT?, or something with "peek" in it.

-- Does READ-CHAR wait for interactive input or return an eof token if
nothing has been buffered up from the keyboard (or comm device, etc)?

-- I oppose the term "stream" and thus the names STREAM?, CURRENT-INPUT-
STREAM, etc., for the reasons Gerry gave.  We use "port".

-- With my Pascal (and English) background, I can't help but think of
features named with "with", like WITH-INPUT-FROM-FILE, as syntax, not
procedures.  [Did you notice how I began the previous sentence?]  I would
prefer a special form: (WITH-INPUT-FROM-FILE <file-name> exp ...).  This is
more consistent with CL's macro WITH-INPUT-FROM-STRING.  The same goes for
WITH-OUTPUT-FROM-FILE.

-- I don't mind your OPEN- and CLOSE- operations, as long as they remain
optional, but I feel bound to implement OPEN and CLOSE compatibly with CL.

-- I like your approach to eof objects.

-- You have no READ-ATOM.  Is there general agreement that READ-ATOM is
unimportant?  We have it only by inheritance from Scheme 84.

Regards,
David Bartley
-------


∂15-Mar-85  0801	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Mar 85  08:00:52 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 15 MAR 85  10:59:37 EST
Date: Fri, 15 Mar 1985  10:58 EST
Message-ID: <CPH.12095236587.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC
Subject: I/O proposal
In-reply-to: Msg of 14 Mar 1985  10:52-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    Date: Thursday, 14 March 1985  10:52-EST
    From: David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    -- DISPLAY-CHAR seems to be a redundant, restricted form of DISPLAY. Since
    DISPLAY is essential, DISPLAY-CHAR should be dropped.

I don't agree.  I think that it is good to have a balanced pair of
procedures for doing character-level I/O.

    -- I oppose the term "stream" and thus the names STREAM?, CURRENT-INPUT-
    STREAM, etc., for the reasons Gerry gave.  We use "port".

Ditto, except that we use "stream" and will cheerfully change it.

    -- With my Pascal (and English) background, I can't help but think of
    features named with "with", like WITH-INPUT-FROM-FILE, as syntax, not
    procedures.  [Did you notice how I began the previous sentence?]  I would
    prefer a special form: (WITH-INPUT-FROM-FILE <file-name> exp ...).  This is
    more consistent with CL's macro WITH-INPUT-FROM-STRING.  The same goes for
    WITH-OUTPUT-FROM-FILE.

I disagree -- proliferation of special forms is a communicable disease.

∂16-Mar-85  1017	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 16 Mar 85  10:17:40 PST
Received: from csnet-relay by MIT-MC.ARPA; 16 MAR 85 13:16:38 EST
Received: from unc by csnet-relay.csnet id ak00871; 16 Mar 85 13:14 EST
Received: by unc (4.12/4.7) id AA03236; Sat, 16 Mar 85 07:34:57 est
Date: Sat, 16 Mar 85 07:34:57 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503161234.AA03236@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  I/O proposal

I think the overall proposal is quite nice.  I do have a couple
of remarks and minor suggestions, though.

1.  I would prefer a settable *eof* variable.  It is useful sometimes
    to specify the value returned on eof.  I also think "eof?" is
    unnecessarily complex (giving implementors free reign is not
    the most important issue here).  Besides, if you ask ten people
    what they think the function "eof?" does, chances are all ten
    will say, "it takes a file as input and returns true iff the
    file is at eof."  No big deal here, though.

2.  I do not think the programmer should be encouraged to change
    the default input/output streams.  This leads to confusing or
    even dangerous behavior when an error or interrupt occurs.
    The exception handler normally wants to operate in the same
    environment as the interrupted routine, in order that the
    user can query the environment (perform stack walkbacks, check
    values of variables, etc.).  Imagine if the handler prints
    a message and queries the user but receives its input from a
    disk file because the default input file has been rebound,
    e.g. "Really delete *.*? (y/n): ".  For this reason, I think
    the names should be "default-input-stream" and
    "default-output-stream", rather than "current-...".  Of course,
    "with-input-from-file" and "with-output-to-file" should not be
    supported.

    I have had experience with this very issue, and troublesome
    problems really do occur.  I do not want to write every piece of
    code to guard against someone changing the default input/output
    files on me.  I guess we could provide "console-input-stream" and
    "console-output-stream" functions, but this seems to complicate
    things unnecessarily.

    I think it's a good practice anyway to use explicit stream
    arguments.

    By the way, why are these functions instead of variables?
    Isn't this (only perhaps) helping implementrs at the expense
    of added complexity?

3.  Why have "call-with-input-file" and "call-with-output-file"
    rather than an expression-oriented syntax?  I think that the
    extra level of nesting will be nasty and people will likely
    just define syntactic extensions to get rid of it anyway.
    (reference my earlier note) I propose:

    (with-input-file (<id> <string>) form ...)
 	and
    (with-output-file (<id> <string>) form ...)

    with the same semantics.  Each set can easily be defined in
    terms of the other, but if one is standard it should be the
    simplest one to use.

4.  I prefer the name "write-char" to "display-char".  I take it
    the rationale is that "write-char" might imply that it may
    be read back in by the function read as a character.  I don't
    think this is really going to cause confusion; after all, it
    may be read back in by read-char, so read-char/write-char is
    parallel to to read/write.

..Kent

∂16-Mar-85  1020	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 16 Mar 85  10:20:02 PST
Received: from csnet-relay by MIT-MC.ARPA; 16 MAR 85 13:16:44 EST
Received: from unc by csnet-relay.csnet id al00871; 16 Mar 85 13:15 EST
Received: by unc (4.12/4.7) id AA06384; Sat, 16 Mar 85 11:38:25 est
Date: Sat, 16 Mar 85 11:38:25 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503161638.AA06384@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  I/O proposal

I would also like the name "read-char-ready?" instead of "listen?".

∂17-Mar-85  0839	@MIT-MC:JINX@MIT-OZ 	I/O proposal  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Mar 85  08:38:49 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 17 MAR 85  11:37:49 EST
Date: 17 Mar 1985  11:37 EST (Sun)
Message-ID: <JINX.12095767900.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Kent Dybvig <dyb%unc.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: I/O proposal
In-reply-to: Msg of 16 Mar 1985  07:34-EST from Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

	Just a few comments:

1.	Having a way to detect the end of file is needed, beyond that,
both alternatives (eof? or *eof*) can be trivially implemented on top
of the other.  I don't feel strongly about either, but I tend to agree
with Kent Dybvig since I view *eof* as more flexible.  If the other
option (eof?) is chosen, I would much rather have the name be
eof-object? .

2.	I disagree that the programmer should not be able to change
the current i/o streams. The debugging problem can be trivially fixed
if the error system/debugger always installs the appropriate stream,
and this can be accomplished easily by appropriate
with-input-from-stream and with-output-from-stream.

	Note that allowing the programmer to change them allows for a
cheap implementation of trasncript-on and transcript-off if the stream
objects are appropriately powerful (which they probably want to be).

	There is good reason for making them functions rather thatn
variables.  If they are variables, the implementation cannot easily
cash the internal components of a stream object in the appropriate
places.  For example, for faster default output the implementation can
cash in the printer the procedures for printing characters and strings
to the current output-stream.  If the variable is changed, the cash
has to be updated which means either that changes to some variables
are noticed (some variables are special, which I think is a bad idea),
or that the printer must check every time it is invoked.  Since
with-output-from..., etc, provide ways of redirecting output, and
furthermore, a procedure set-current-output-stream! can be provided,
there is no functionality lost and the implementation has more freedom.

3.	Having functions rather than special forms is in general good,
especially since we have not decided whether special form (and macro)
names are scoped in the same environment or in a different one, and
other such issues.

	Note that these functions parallel
call-with-current-continuation on which we agreed at the workshop, and
the reasons are mostly the same.

4.	I don't particularly care about the name for
is-character-available? (listen?), but there is an important issue
which I believe has not been raised.

	On interactive streams users may have the possibility of
erasing typed characters.  What happens if listen? returns true and
then the user erases the character?  The program which invoked listen?
will probably attempt to read a character thinking that it will not
hang but it will.  We had this bug and went to a fair amount of hair
to get it fixed.

	I see two possible solutions to this:

	- Listen? locks the character if it returns true.  This is
ugly since read-character may not be performed for a while, and may
even be bypassed (error exit, etc.)

	- Listen? is polymorphic and returns either '() or a character
object if one is available.  This assumes that the set of character
objects is disjoint from the set { '() }.  No further call to read is
needed.  Listen? would then more appropriately be called
non-blocking-read-char.  I advocate for this solution.

5.	We have not talked at all about keyboard interrupts.  It seems
to me that any reasonable implementation should provide a way for the
user to (at least) abort an infinite loop.  It would be nice if we had
a simple standard mechanism for doing this, but implementations would
be free to have more keyborad interrupts (we currently have 5 by
default).  I propose that we choose some control character (↑G, for
example) which on all implementations and unless inhibited (an editor
may want to do this) will interrupt Scheme and make it return to the
top-level read-eval-print loop.

∂17-Mar-85  1027	@MIT-MC:CPH@MIT-OZ 	I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Mar 85  10:26:56 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 17 MAR 85  13:24:58 EST
Date: Sun, 17 Mar 1985  13:24 EST
Message-ID: <CPH.12095787388.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Cc:   Kent Dybvig <dyb%unc.csnet@CSNET-RELAY.ARPA>, scheme@MIT-MC.ARPA
Subject: I/O proposal
In-reply-to: Msg of 17 Mar 1985  11:37-EST from Bill Rozas <JINX>

    Date: Sunday, 17 March 1985  11:37-EST
    From: Bill Rozas <JINX>

    1.	Having a way to detect the end of file is needed, beyond that,
    both alternatives (eof? or *eof*) can be trivially implemented on top
    of the other.  I don't feel strongly about either, but I tend to agree
    with Kent Dybvig since I view *eof* as more flexible.  If the other
    option (eof?) is chosen, I would much rather have the name be
    eof-object? .

I don't think that *EOF* is a good idea, for the following reason: if
the I/O primitives are expected to return this object, they will have
to return it, and if they are written in assembly or some other
non-Scheme language it would require them to do a variable reference.
Or, at the very least, to have some kind of Scheme wrapper that either
passed them the eof object, or detected that they had returned some
other object and substituted that one.

I vastly prefer the idea of a small fixed set of end of file objects,
and I wish that I had thought up the idea myself.  However, I agree
that EOF-OBJECT? is a much better name.

If it is felt that there is a need for something like *EOF*, I would
feel better about having a procedural binder, something like

(WITH-EOF-OBJECT <object> (LAMBDA () ...))

which would give the implementer more freedom.

    2.	I disagree that the programmer should not be able to change
    the current i/o streams. The debugging problem can be trivially fixed
    if the error system/debugger always installs the appropriate stream,
    and this can be accomplished easily by appropriate
    with-input-from-stream and with-output-from-stream.

This has been my experience -- we have had this stuff running for
quite some time without problems.

∂17-Mar-85  2041	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	assertions are better than types  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Mar 85  20:41:33 PST
Received: from csnet-relay by MIT-MC.ARPA; 17 MAR 85 23:40:21 EST
Received: from indiana by csnet-relay.csnet id aa08590; 17 Mar 85 23:36 EST
Date: Sun, 17 Mar 85 17:21:05 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA03798; Sun, 17 Mar 85 17:21:05 est
To: scheme@mit-mc.ARPA
Subject: assertions are better than types

Gerry's numbers proposal is the first attempt I've ever seen at 
doing numbers right, and I'm very excited about it.  I've become 
concerned about the effectiveness of the type-restricted 
operators, however, and I'd like to offer an alternative 
proposal.  

First of all, let me state my understanding of Gerry's proposal, 
as I edited it for the Revised Revised Report.  (I know it isn't 
written very well -- my concern was growing as I wrote it.) 

---------------------------------------------------------------- 


(number op)                                             procedure
(complex op)                                            procedure
(real op)                                               procedure
(rational op)                                           procedure
(integer op)                                            procedure

These procedures take a numeric operator op and return a 
procedure that acts like op except that it is restricted to 
operate on numbers of the specified type and to return numbers 
of the specified type.  The idea of these procedures is 
expressed by 

  (define make-type-restrictor
    (lambda (type?)
      (lambda (op)
        (lambda args
          (if (every type? args)
              (let ((ans (apply op args)))
                (if (type? ans)
                    ans
                    (error "Bad result from type-restricted operator")))
              (error "Bad argument to type-restricted operator"))))))

  (define number (make-type-restrictor number?))
  (define complex (make-type-restrictor complex?))
  (define real (make-type-restrictor real?))
  (define rational (make-type-restrictor rational?))
  (define integer (make-type-restrictor integer?))

where EVERY returns true if its first argument, a predicate, is 
true of every element of its second argument, a list.  

Some implementations may provide a mechanism whereby the 
programmer can request that these type restriction procedures be 
interpreted as assertions intended to make the code run faster 
rather than as requests for type checks.  

                ((real sqrt) 5)         -->  2.236067977
                ((real sqrt) -1)        -->  error
                ((integer sqrt) 10)     -->  error

The programmer who wrote the last example probably wanted to 
compute (TRUNCATE ((REAL SQRT) 10)).  

[Gerry's rationale would go here.] 

---------------------------------------------------------------- 


My objections: 

1.  Speaking for myself, I would not want to clutter my code 
with all these type-restricted operators as I write the code, 
because it would make the code less readable.  (I guess 
readability is more important to my debugging processes than are 
type checks.) I would be willing to add type assertions when the 
time came to make the code run fast.  Hence for me at least, the 
type restrictions would be more important as advice to the 
compiler than as debugging aids.  

2.  The type restrictors require that all operands and the 
result be of the same type.  This works reasonably well for 
numeric operators but is going to be awkward when the time comes 
to generalize it to other operators.  How am I going to tell the 
compiler that the first argument to vector-ref is a vector of 
strings? 

3.  Statically typed languages are mistaken in associating types 
with variables, and Gerry is on the right track to associate 
type restrictions with operators, but I think most of us would 
agree that the right thing to do is to associate types with 
values.  That leads to my proposal, which follows: 

---------------------------------------------------------------- 


(assert property? obj)                                  procedure

PROPERTY? must be a total (everywhere defined) unary predicate 
with no side effects.  Returns obj.  It is an error if PROPERTY? 
is not true of obj, but implementations are not required to 
detect the error.  

Rationale: In interpreted code, assertions can be used to check 
types, loop invariants, and other assertions.  In compiled code, 
calls to ASSERT have zero overhead but help the compiler to 
produce better code.  The ASSERT procedure is a moby 
generalization of Common Lisp's special form called THE, and of 
MacLisp's FIXNUM-IDENTITY and FLONUM-IDENTITY.  

---------------------------------------------------------------- 


Examples: 

Here is Gabriel's tak benchmark with type-restricted operators 
as in Gerry's proposal: 

(define (tak x y z) 
  (if (not (<? y x))      ; notice that you can't say (integer <?)
      z
      (tak (tak ((integer -1+) x) y z)
	   (tak ((integer -1+) y) z x)
	   (tak ((integer -1+) z) x y))))

Here it is with assertions: 

(define (tak x y z) 
  (assert integer? x)
  (assert integer? y)
  (assert integer? z)
  (if (not (<? y x))
      z
      (tak (tak (-1+ x) y z)
	   (tak (-1+ y) z x)
	   (tak (-1+ z) x y))))

You could also wrap all the references (or calls) to tak in an 
integer declaration, but it's easy to see that that's 
unnecessary.  

Here is doubly recursive Fibonacci: 

; Gerry's proposal 

(define (fib n) 
  (if (<? n 2)    ; notice again that (integer <?) won't work
      n
      ((integer +) (fib ((integer -) n 1)) (fib ((integer -) n 2)))))

; With assertions 

(define (fib n) 
  (assert integer? n)
  (if (<? n 2)
      n
      (+ (assert integer? (fib (- n 1)))
         (assert integer? (fib (- n 2))))))

; With a good compiler, this would suffice.  

(define (fib n) 
  (assert integer? n)
  (if (<? n 2)
      n
      (+ (fib (- n 1)) (fib (- n 2)))))

Of course, if you really wanted fib to run fast, and you didn't 
intend to use it with arguments greater than 40, and excellent 
compilers were widespread, then you would probably say something 
like 

(define fib 
  (let ((fixnum?
	  (lambda (x)
	    (and (integer? x)
		 (not (negative? x))
		 (<? x 100000000)))))
    (rec fib
      (lambda (n)
        (assert fixnum? n)
        (if (<? n 2)
            n
            (+ (assert fixnum? (fib (- n 1)))
	       (assert fixnum? (fib (- n 2)))))))))




∂17-Mar-85  2054	@MIT-MC:CPH@MIT-OZ 	assertions are better than types   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Mar 85  20:54:04 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 17 MAR 85  23:53:02 EST
Date: Sun, 17 Mar 1985  23:52 EST
Message-ID: <CPH.12095901736.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Will Clinger <willc%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: assertions are better than types
In-reply-to: Msg of 17 Mar 1985  17:21-EST from Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

Nice!  I like it.

∂17-Mar-85  2248	@MIT-MC:KMP@SCRC-STONY-BROOK 	assertions are better than types   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Mar 85  22:47:47 PST
Received: from SCRC-STONY-BROOK by MIT-MC via Chaosnet; 18 MAR 85  01:46:45 EST
Received: from SCRC-RIO-DE-JANEIRO by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 198848; Mon 18-Mar-85 01:47:30-EST
Date: Mon, 18 Mar 85 01:45 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: assertions are better than types
To: willc%indiana.csnet@CSNET-RELAY.ARPA, scheme@MIT-MC.ARPA
In-Reply-To: The message of 17 Mar 85 17:21-EST from Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Message-ID: <850318014558.4.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>

I haven't had a chance to go over the recent burst of proposals in
enough depth to comment, but will get to it.

Let me mention, though, while I'm thinking about it, that with regard to:

    Date: Sun, 17 Mar 85 17:21:05 est
    From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>

    ... Here is doubly recursive Fibonacci: 

    ; Gerry's proposal 

    (define (fib n) 
      (if (<? n 2)    ; notice again that (integer <?) won't work
	  n
	  ((integer +) (fib ((integer -) n 1)) (fib ((integer -) n 2)))))

    ; With assertions 

    (define (fib n) 
      (assert integer? n)
      (if (<? n 2)
	  n
	  (+ (assert integer? (fib (- n 1)))
	     (assert integer? (fib (- n 2))))))

    ; With a good compiler, this would suffice.  

    (define (fib n) 
      (assert integer? n)
      (if (<? n 2)
	  n
	  (+ (fib (- n 1)) (fib (- n 2)))))

Please be careful when writing your compilers not to copy the Maclisp bug
where:

(DEFUN F (X Y) (DECLARE (FIXNUM X Y)) (PLUS X Y))

turns into a single-instruction addition, ignoring overflow. Gerry's proposal
does not specify much of any way to get code that can do that. It was an
unfortunate mistake since when X and Y are large, the addition can overflow
and bad values can get returned (something GJS's proposal frowns on).

When we thought about this in T a long time ago, we noticed that there are
some kinds of integers which can be said in the abstract to be suitable for
machine-instruction operations. For example, things that count other things
in the address space (eg, array indices) are somehow bounded in a way that
you could usefully take advantage of. It may be useful, therefore, to create
a type called something like INDEX which is like INTEGER but is bounded by
the number of addressable things in the world. Then one can write:
 (ASSERT INDEX? (+ (ASSERT INDEX? X) (ASSERT INDEX? Y)))
to get a machine-instruction addition in those cases where it is reliable.
Systems which had addressing schemes that made it impossible to place a bound
on the size of an INDEX could just treat it as synonymous with INTEGER, which
would be invisible to the user except performance-wise.

By the way, changing the subject slightly, but still on the topic of assertions,
my original proposal for T was to have PLUS and + be synonyms, but to have
operators ASSERT and MAP-ASSERT which let one write customizations such as:

 (DEFINE-OPEN-CODED (+ . ARGS)
   (ASSERT INTEGER? (APPLY PLUS (MAP-ASSERT INTEGER? ARGS))))

 so that (+ X Y) 
 would be like (ASSERT INTEGER? (PLUS (ASSERT INTEGER? X) (ASSERT INTEGER? Y)))

or

 (DEFINE-OPEN-CODED (INTEGER OPERATOR)
   (LAMBDA ARGS (ASSERT INTEGER? (APPLY OPERATOR (MAP-ASSERT INTEGER? ARGS)))))

 so that ((INTEGER +) X Y)
 would be like (ASSERT INTEGER? (+ (ASSERT INTEGER? X) (ASSERT INTEGER? Y)))

I think MAP-ASSERT got lost from T somewhere along the way, but perhaps it 
would be worth picking back up if people thought this sort of thing was fun.

∂18-Mar-85  1045	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  10:45:12 PST
Received: from csnet-relay by MIT-MC.ARPA; 18 MAR 85 13:25:10 EST
Received: from unc by csnet-relay.csnet id ae00998; 18 Mar 85 13:22 EST
Received: by unc (4.12/4.7) id AA18455; Sat, 16 Mar 85 22:12:45 est
Date: Sat, 16 Mar 85 22:12:45 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503170312.AA18455@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  I/O proposal

(This note should have come before the others, as it was
referenced in one of them -- sorry.)

>    I disagree -- proliferation of special forms is a communicable disease.
    
Addition of new syntax where new syntax makes sense is never
harmful.  It's much more clumsy to use a function when what
really makes sense is a proceedure.  Ninety-nine times out
of a hundred people are going to type:
    (with-output-to-file "fudmich"
        (lambda ()
            ...))
Adding an extra level of complexity (not to mention an extra
level of nesting).
    
If we continue to use functions where syntax is appropriate,
pretty soon someone will suggest that the reader syntax
"#'exp" should mean "(lambda () exp)".
    
If keeping the language small is the goal, proliferation of
functions is more harmful; the ``core'' set must include only
special forms that cannot be implemented using syntactic-
extension, plus all of the functions.  I can preprocess a
program on my system to take out the syntax before sending
it to you to run it on your system, but you must have the
functions I call (unless I send them all to you).
    
Granted, with this particular special form, the standard does
not give us enough information to write it as syntax; this is
a shortcoming in the standard, not in syntactic-extension.
    
..Kent

∂18-Mar-85  1049	JAR@MIT-MC 	I/O proposal 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  10:48:59 PST
Date: 18 March 1985 13:48-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  I/O proposal
To: dyb%unc.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of Sat 16 Mar 85 22:12:45 est from Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

    Date: Sat, 16 Mar 85 22:12:45 est
    From: Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>

    >   I disagree -- proliferation of special forms is a communicable disease.
        
    Addition of new syntax where new syntax makes sense is never
    harmful.  It's much more clumsy to use a function when what
    really makes sense is a proceedure.  Ninety-nine times out
    of a hundred people are going to type:
        (with-output-to-file "fudmich"
            (lambda ()
                ...))
    Adding an extra level of complexity (not to mention an extra
    level of nesting).

I would not argue strongly if you claimed that antispecialformism was a
purely religious position (although I'd wonder, since it's so strongly
held in some camps, such as the ones I belong to).  One rational
argument, however, might be not necessarily language simplicity, as you
suggested, but rather, program analyzability.  Any program-analyzing
program or human must know about ALL special forms in order to do things
such as free variable analysis and substitution; and there is much one
can say about a program without having ANY knowledge of the values of
free variables.  So, generally speaking, special forms add to the
complexity of program analysis, whereas procedures (i.e.  bindings) do
not, and therefore special forms are to be avoided.

This argument does not necessarily apply to macros (since macro forms
can be expanded), but since Essential Scheme is militant in not having a
theory of macros, that doesn't help much.

    If we continue to use functions where syntax is appropriate,
    pretty soon someone will suggest that the reader syntax
    "#'exp" should mean "(lambda () exp)".

Actually this is not so absurd.  I have from time to time toyed with the
idea of a reader syntax for (lambda () ...) in analogy to that for
(quote ...) for this very reason - the presence of such a thing would
often shoot down the conciseness arguments sometimes put forth in favor
of special forms.

Jonathan

∂18-Mar-85  1123	@MIT-MC:GJS@MIT-OZ 	Re:  I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  11:22:38 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 18 MAR 85  14:20:44 EST
Date: Mon 18 Mar 85 14:09:28-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re:  I/O proposal
To: dyb%unc.csnet@CSNET-RELAY.ARPA
cc: scheme@MIT-MC.ARPA
In-Reply-To: Message from "Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>" of Mon 18 Mar 85 14:02:16-EST

I think that syntax is not the right thing if we can avoid it.  For
example, one can pass a procedure WITH-OUTPUT-TO-FILE as an argument
or return it as a value... We cannot do that with a syntactic form.

Thus, unless there are overwhelming reasons for introducing syntax, we
really should not do so.

-------

∂18-Mar-85  1159	@MIT-MC:GJS@MIT-OZ 	Re: assertions are better than types    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  11:59:28 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 18 MAR 85  14:56:49 EST
Date: Mon 18 Mar 85 14:01:07-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: assertions are better than types
To: willc%indiana.csnet@CSNET-RELAY.ARPA
cc: scheme@MIT-MC.ARPA
In-Reply-To: Message from "Will Clinger <willc%indiana.csnet@csnet-relay.arpa>" of Sun 17 Mar 85 23:42:56-EST

Hi.  Before you jump, I just want to clarify a few points about what I
meant by type-restricted operators -- I know I didn't say this in the
draft I sent you, but I didn't realize the scope of possible
confusion.  I rspond pointwise:


Willc:  Speaking for myself, I would not want to clutter my code 
	with all these type-restricted operators as I write the code, 
	because	it would make the code less readable.  (I guess 
	readability is more important to my debugging processes than are 
	type checks.) I would be willing to add type assertions when the 
	time came to make the code run fast.  Hence for me at least, the 
	type restrictions would be more important as advice to the 
	compiler than as debugging aids.  


GJS:  I agree, usually we would not write the ugly kind of code which
is illustrated below:

(define (tak x y z) 
  (if (not (<? y x))      ; notice that you can't say (integer <?)
      z
      (tak (tak ((integer -1+) x) y z)
	   (tak ((integer -1+) y) z x)
	   (tak ((integer -1+) z) x y))))

Instead we would write something like this:

(define tak
  (let ((-1+ (integer -1+))
	(<? (integer <?)))	;Note that we can say this, see below!
    (lambda (x y z) 
      (if (not (<? y x))	
	  z
	  (tak (tak (-1+ x) y z)
	       (tak (-1+ y) z x)
	       (tak (-1+ z) x y))))))

Presumably, with a good compiler it would be just as efficient to
write:

(define (tak x y z) 
  (let ((-1+ (integer -1+))
	(<? (integer <?)))	;Note that we can say this, see below!
    (if (not (<? y x))	
	z
	(tak (tak (-1+ x) y z)
	     (tak (-1+ y) z x)
	     (tak (-1+ z) x y)))))



Willc:	The type restrictors require that all operands and the 
	result be of the same type.  This works reasonably well for 
	numeric operators but is going to be awkward when the time comes 
	to generalize it to other operators.  How am I going to tell the 
	compiler that the first argument to vector-ref is a vector of 
	strings? 

Willc:	These procedures take a numeric operator op and return a 
	procedure that acts like op except that it is restricted to 
	operate on numbers of the specified type and to return numbers 
	of the specified type.


GJS: The type restrictions are not intended to be simply error-checking
on the type of the inputs and outputs, but rather to be an entry to a
more coherent system built on the numerical tower.  The idea is that
for each kind of number there is a set of appropriate kinds of operations
that make sense for it.  For example, the INTEGERS are a ring, hence they
do not support arbitrary division.  This does not stop us from defining
"/" for the INTEGERS to be anything we like, such as an entry to higher
types on the tower.  Additionally, I am not even attempting to clarify
the types for things like strings or vectors of strings, since they do
not have the mathematical structure of numbers... This is trying to be a
coherent theory about numbers, rather than an incoherent theory of
everything.

For example, Hal and I have been hacking a new version of generic 
arithmetic based on these principles -- I include a fragment for your
amusement.  Basically, there is an operation table, and "restrictions"
like INTEGER are things that transform the generic operator, like +,
into the actual operation from the table.

The following code creates a "rational package" for a
given RING, the new objects have type FIELD.

;;; Rational operations generator

(define (make-rational-operations! ring field)

  (let ((+r (ring +)) (-r (ring -)) (*r (ring *)) (negate-r (ring negate)) 
	(=r (ring =)) (gcd (ring gcd)) (quotient (ring quotient))
	(sign-r (ring sign)) (one-r (ring 'one)) (zero-r (ring 'zero)))

    (define (make-rational n d)
      (let ((s (sign-r d)))
	(cond ((=r one-r s)
	       (cons '*numeric-type*
		     (cons field (cons n d))))
	      ((=r zero-r s)
	       (error "Bad rational construction" field (list n d)))
	      (else
	       (cons '*numeric-type*
		     (cons field
			   (cons (quotient n s)
				 (quotient d s))))))))
    
    (define numer caddr)
    (define denom cdddr)

    (define (+←rational x y)
      (let ((d1 (gcd (denom x) (denom y))))
	(if (=r one-r d1)    ;GIGO
	    (make-rational (+r (*r (numer x) (denom y))
			      (*r (denom x) (numer y)))
			   (*r (denom x) (denom y)))
	    (let ((dx/d1 (quotient (denom x) d1)))
	      (let ((tem (+r (*r (quotient (denom y) d1) (numer x))
			    (*r dx/d1 (numer y)))))
		(let ((d2 (gcd tem d1)))
		  (make-rational (quotient tem d2)
				 (*r dx/d1
				    (quotient (denom y) d2)))))))))

    (define (-←rational x y)
      (+←rational x (make-rational (negate-r (numer y)) (denom y))))

    (define (*←rational x y)
      (let ((d1 (gcd (numer x) (denom y)))
	    (d2 (gcd (numer y) (denom x))))
	(make-rational (*r (quotient (numer x) d1)
			  (quotient (numer y) d2))
		       (*r (quotient (denom x) d2)
			  (quotient (denom y) d1)))))

    (define (/←rational x y)
      (*←rational x (make-rational (denom y) (numer y))))

    (define (=←rational x y)
      (and (=r (numer x) (numer y)) (=r (denom x) (denom y))))

    (define (negate-rational x)
      (make-rational (negate-r (numer x)) (denom x)))

    (define (recip-rational x)
      (make-rational (denom x) (numer x)))

    (define (raise i)
      (make-rational i one-r))

    (put-coercion! raise ring field)

    (put-op! (raise zero-r) 'zero field)
    (put-op! (raise one-r) 'one field)

    (put-op! +←rational + field)
    (put-op! -←rational - field)
    (put-op! *←rational * field)
    (put-op! /←rational / field)
    (put-op! =←rational = field)

    (put-op! negate-rational negate field)
    (put-op! recip-rational recip field)

    (put-op! (lambda (x) (sign-r (numer x))) sign field)

    (put-op! numer numerator field)
    (put-op! denom denominator field)

    ))


;;;Now we can use this to define the rationals over integers

(define (rational op) (get-op op rational))

(define (rational? x)
  (or (integer? x)
      (eq? (numeric-type x) rational)))

(make-rational-operations! integer rational 'rational)

;;;For these particular rationals, we may also want some additional
;;;operations that are not sensible for arbitrary rationals, e.g.,
;;;based upon polynomial rings.  For example:


(define (raise-rational-unary-operation op)
  (lambda (x) (op (rational->real x))))

(put-op! (raise-rational-unary-operation sqrt) sqrt rational)
(put-op! (raise-rational-unary-operation sin) sin rational)
(put-op! (raise-rational-unary-operation cos) cos rational)
(put-op! (raise-rational-unary-operation tan) tan rational)

(put-op! (raise-rational-unary-operation real-part) real-part rational)
(put-op! (raise-rational-unary-operation imag-part) imag-part rational)
(put-op! (raise-rational-unary-operation magnitude) magnitude rational)
(put-op! (raise-rational-unary-operation angle) angle rational)

-------

∂18-Mar-85  1210	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Arithmetic overflow
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  12:09:58 PST
Received: from csnet-relay by MIT-MC.ARPA; 18 MAR 85 15:08:58 EST
Received: from indiana by csnet-relay.csnet id a001575; 18 Mar 85 14:38 EST
Date: Mon, 18 Mar 85 10:48:24 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA03030; Mon, 18 Mar 85 10:48:24 est
To: scheme@mit-mc.ARPA
Subject: Arithmetic overflow

Kent Pitman points out:

>Please be careful when writing your compilers not to copy the Maclisp bug
>where:
>
>(DEFUN F (X Y) (DECLARE (FIXNUM X Y)) (PLUS X Y))
>
>turns into a single-instruction addition, ignoring overflow. Gerry's proposal
>does not specify much of any way to get code that can do that. It was an
>unfortunate mistake since when X and Y are large, the addition can overflow
>and bad values can get returned (something GJS's proposal frowns on).

I agree whole-heartedly.  Like Gerry's proposal, the ASSERT procedure does
not give the programmer the ability to specify that overflow is to be ignored,
though it can be used to assert that a result is within a certain range.

My last fibonacci example was perhaps too subtle.  In computing (fib 40), the
arguments to + are always less than 100000000 (the constant appearing in the
fixnum? procedure), but the result is greater than 100000000.  A compiler that
assumes that the result of an addition is never greater than the operands is
simply buggy.

				Peace, Will Clinger


∂18-Mar-85  1545	@MIT-MC:linus!ramsdell@mitre-bedford 	Pointer-less stack allocated arrays. 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  15:39:44 PST
Received: from mitre-bedford by MIT-MC.ARPA; 18 MAR 85 18:38:27 EST
Date: 18 Mar 1985 18:36:50-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA07064; Mon, 18 Mar 85 15:17:32 est
Date: Mon, 18 Mar 85 15:17:32 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503182017.AA07064@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: Pointer-less stack allocated arrays.

I recently visited Harvard and had an interesting
conversation with Stavros Macrakis.  He is an
Ada proponent with considerable experience with
Lisp, in particular, MacLisp.  He was very active
in the Macsyma project and gained much knowledge
about MacLisp's implementation. 

I brought up the subject of extensible languages
in reference to Richard Schooler's masters thesis
called "Partial Evaluation as a means of Language
Extensibility", MIT/LCS/TR-324, August 1984.  The
thesis suggests that Scheme makes a good intermediate
language; very suitable for partial evaluation.

Stavros immediately rejected the notion that Scheme
makes a good intermediate language because its model
of data is too general.  For example, consider the
task of taking the dot product of two vectors represented
by two arrays of floating point numbers.  Since arrays can
be returned from the function in which they are created,
they must be allocated from the heap.  Since garbage collection
can change the origin of the array, all references to elements
in the array must be accompanied with a reference to the array
header.  Thus the compiled code for Scheme can never be as
good as that produced by an Ada compiler said Starvos.

Many years ago, I asked Jonathan Rees if the T compiler could
place arrays on the stack when appropriate and eliminate the
unneccessary indirection in numerical arrays by replacing
pointers to floating point numbers with the actual numbers
as the array elements.  He claimed compiler declarations
would make this possible, but had many other more pressing issue 
to worry about in regards to the T compiler.  I am wondering
if there is interest in using ASSERT to allow the elimination of
many pointers in some programs.
John

∂18-Mar-85  2056	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Re: I/O proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Mar 85  20:55:51 PST
Received: from csnet-relay by MIT-MC.ARPA; 18 MAR 85 23:54:51 EST
Received: from indiana by csnet-relay.csnet id ab04361; 18 Mar 85 23:38 EST
Date: Mon, 18 Mar 85 16:46:58 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA08003; Mon, 18 Mar 85 16:46:58 est
To: scheme@mit-mc.ARPA
Subject: Re: I/O proposal

We thank everyone for their comments on the I/O proposal.  Here
are our responses.

>Also, I think that you should have both "STREAM?" and its components
>"INPUT-STREAM?" and "OUTPUT-STREAM?", because it makes more
>information available without really constraining the implementation
>in any fundamental way.  Clearly bidirectional streams can satisfy
>both predicates.

Agreed.  Any dissent?

----------------------------------------------------------------

>The only objection I have is the
>use of the word STREAM for the IO stuff.  My problem is that we used that
>word all through chapter 3 of our book to mean the functional programming
>idea of (potentially) infinite sequence.  It will be very painful to change
>that.  I propose that the word be changed to one of CHANNEL, PIPE, PORT, TUBE,
>or any other appropriate euphemism.  I believe that my use of the word STREAM
>is consistent with that of other authors on functional programming.

>-- I oppose the term "stream" and thus the names STREAM?, CURRENT-INPUT-
>STREAM, etc., for the reasons Gerry gave.  We use "port".

Good point, so the names will change as follows:

	old name			new name

	stream?				input-port?
					output-port?
	current-input-stream		current-input-port
	current-output-stream		current-output-port
	close-input-stream		close-input-port
	close-output-stream		close-output-port

----------------------------------------------------------------

>-- What happened to the names PRIN1 and PRINC?  Are your WRITE and DISPLAY
>meant to be equivalent, respectively, to PRIN1 and PRINC?  As I understand
>page 382 of the Common LISP (CL) book, your WRITE is not incompatible with
>CL's.  Likewise, CL doesn't seem to have a DISPLAY.  However, I am bothered
>by my intuition that DISPLAY should be a terminal-oriented operation.
>
>   Bottom line: I vote to go with WRITE and DISPLAY, but the names PRIN1
>and PRINC should be reserved as well (as optional aliases).  The PRINT
>operation should also be optional, with the CL-compatible meaning we agreed
>on at the workshop.

Yes, WRITE and DISPLAY correspond to Common Lisp's PRIN1 and
PRINC.  For that matter they correspond to T's PRINT and DISPLAY,
and to Scheme-84's DISPLAY and PRINT.  Common Lisp's WRITE takes
a stream as a keyword argument whereas Scheme's WRITE takes a
port as an optional argument.  If that incompatibility doesn't
bother you then it certainly doesn't bother us.

PRINC and PRINT are used in the Abelson and Sussman book, but we
don't think they deserve or need formal status.

----------------------------------------------------------------

>2. "A different set of procedures will be needed to create streams from
>and to strings, and the closing procedures should still work on them.
>It seems that closing a string output stream should yield a string, but
>it isn't clear what should be returned when a file output stream is
>closed."
>
>I don't understand this at all. The phrase "create streams from and to
>strings" is rather difficult to parse, which doesn't help.

Scheme doesn't have anything comparable to Common Lisp's
READ-FROM-STRING, WRITE-TO-STRING, WITH-INPUT-FROM-STRING, and
WITH-OUTPUT-TO-STRING.  When we get around to adding those
capabilities, we will want to package the strings up to look like
ordinary I/O ports that can be passed as the optional argument to
READ and WRITE.  It appears that the designers of Common Lisp
didn't quite figure out how they wanted to do it either.

----------------------------------------------------------------

>3. Are with-input-from-file and with-output-from-file the only way to
>change the value of (current-input-stream) and (current-output-stream) ?
>If so, shouldn't they be essential ?

We agree that this is somewhat inconsistent, but there are
difficulties involved with specifying the correct semantics for
WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE, as well as difficulties
involved with implementing them correctly, so for the time being...

WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE are the only ways
defined in the proposal to change the default input or output
ports.  Implementations may feel that the default ports should
always be the keyboard and screen, or they may prefer alternative
ways to change the default ports.  The main reason for making
WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE optional rather than
essential, however, is that we are not certain of the best way
for them to interact with escape procedures, and it seems a good
idea to keep uncertainties like that out of the essential
language until we understand them better.

----------------------------------------------------------------

>-- DISPLAY-CHAR seems to be a redundant, restricted form of DISPLAY. Since
>DISPLAY is essential, DISPLAY-CHAR should be dropped.

At the workshop it was emphasized that characters may overlap
with numbers, strings, or what have you.  If characters are just
numbers, then (DISPLAY #\SPACE) will print something like "32"
whereas (WRITE-CHAR #\SPACE) will print " " (without the double
quotes, of course).

>I wonder why you chose the name "DISPLAY-CHAR" rather than
>"WRITE-CHAR"?  I prefer "WRITE-CHAR" because it has no connotations of
>display terminals, or of being viewed by a human; it says, simply,
>that the character was written down somewhere.

WRITE-CHAR it is.

----------------------------------------------------------------

>I don't see any reason for LOAD and CURRENT-INPUT-STREAM to interact,
>and I think it is much better for them not to.  If they don't interact
>you have a much better invariants on each, e.g.: doing LOAD on a file is
>the same as doing LOAD on a file consisting of the string "(begin "
>appended to the file appended to the string ")".

We agree entirely, and are flushing the sentence in question.

----------------------------------------------------------------

>-- The name LISTEN? also is slightly unintuitive to me; how about INPUT?,
>or MORE-INPUT?, or something with "peek" in it.

LISTEN? is named after the LISTEN predicate in Common Lisp.
"Peek" calls to mind MacLisp's TYIPEEK, which is unrelated.
We're willing to change the name, and the following are the leading
candidates:
		CHAR-READY?
		INPUT-READY?

Please send your votes to brooks@indiana before 25 March.

----------------------------------------------------------------

>-- Does READ-CHAR wait for interactive input or return an eof token if
>nothing has been buffered up from the keyboard (or comm device, etc)?

It waits.

----------------------------------------------------------------

>-- With my Pascal (and English) background, I can't help but think of
>features named with "with", like WITH-INPUT-FROM-FILE, as syntax, not
>procedures.  [Did you notice how I began the previous sentence?]  I would
>prefer a special form: (WITH-INPUT-FROM-FILE <file-name> exp ...).  This is
>more consistent with CL's macro WITH-INPUT-FROM-STRING.  The same goes for
>WITH-OUTPUT-FROM-FILE.

We prefer procedures to special forms, and we followed MIT's
names here.  It is hard to come up with good names for these
procedures.



    Thanks again to all who are commenting on the proposals.

				Gary Brooks and Will Clinger


∂19-Mar-85  0456	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 -- long message to scheme@mit-mc    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  04:56:45 PST
Received: from CSNET-SH by MIT-MC.ARPA; 19 MAR 85 07:55:45 EST
To: scheme@MIT-MC.ARPA
cc: willc%indiana.csnet@CSNET-SH.ARPA
Subject: Message a011267 -- long message to scheme@mit-mc
Reply-to: cic@CSNET-SH.ARPA
Date: 19 Mar 85 07:45:58 EST (Tue)
From: "Charlotte D. Mooers" <postmaster@CSNET-SH.ARPA>

This message was rejected by mit-mc for the following reason:
'Message is too large to mail; use FTP.'

Since FTP (file transfer protocol) is not possible between indiana
and mit-mc, I have split up the message into three sections of
1000, 1000 and 695 lines each, which I will send separately.
In the future, please agree on a limit to the length of file that
you will transmit by mail to mit-mc.

---Charlotte Mooers
   CSNET Staff

∂19-Mar-85  0459	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 1
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  04:58:56 PST
Received: from CSNET-SH by MIT-MC.ARPA; 19 MAR 85 07:56:10 EST
To: scheme@MIT-MC.ARPA
Subject: Message a011267 LONG message - part 1
Reply-to: cic@CSNET-SH.ARPA
Date: 19 Mar 85 07:48:45 EST (Tue)
From: "Charlotte D. Mooers" <postmaster@CSNET-SH.ARPA>


Received: from csnet-relay.arpa by CSNET-SH.ARPA id a028166; 18 Mar 85 13:26 EST
Date:     Mon, 18 Mar 85 10:55:42 EST
From:     CSNET-RELAY Memo Service (MMDF) <mmdf@CSNET-RELAY.ARPA>
Subject:  Failed mail  (msg.a011267)
Sender:   mmdf@CSNET-RELAY.ARPA
To:       Postmaster@CSNET-RELAY.ARPA

    Your message could not be delivered to
'scheme@mit-mc.ARPA (host: mit-mc.arpa) (queue: smtp)' for the following
reason:  ' Message is too large to mail; use FTP.'


    Your message follows:

Received: from indiana by csnet-relay.csnet id a011267; 18 Mar 85 9:36 EST
Date: Mon, 18 Mar 85 01:24:29 est
From: willc@Indiana (Will Clinger)
Received: by iuvax.UUCP; id AA06606; Mon, 18 Mar 85 01:24:29 est
To: scheme@mit-mc
Subject: DRAFT of Revised Revised Report (LONG message)

Here is the DRAFT of the final report on the Brandeis workshop.
It is missing all its appendices, and a couple of sections that
deal with the lexical syntax of numbers need more work.  Please
read it and tell me what you think.  We'd like to have your
comments by 1 April so we can send it to press.

The font information has been stripped for posting to
scheme@mit-mc. Some ambiguities probably result, but please don't
get upset about them.

If you have anything more to say about Chris Hanson's work on
strings, please say it soon.  We'd like to include Chris's work
in this report.
				-- Will Clinger
				willc@indiana


                        Table of Contents




Part I: Introduction to Scheme 

    I.0   Brief history of Scheme                                
    I.1   Syntax of Scheme                                       
    I.2   Semantics of Scheme                                    


Part II: A catalog of Scheme 

   II.0   Notational conventions                                 
   II.1   Special forms                                          
   II.2   Booleans                                               
   II.3   Equivalence predicates                                 
   II.4   Pairs and lists                                        
   II.5   Symbols                                                
   II.6   Numbers (part 1)                                       
   II.7   Numbers (part 2)                                       
   II.8   Strings                                                
   II.9   Vectors                                                
   II.10  The object table                                        
   II.11  Procedures                                             
   II.12  Ports                                                  
   II.13  Input                                                  
   II.14  Output                                                 

References                                                       

Index (not yet ready)                                            


!Acknowledgements 


This report is primarily the work of a group of people who met 
at Brandeis University for two days in October 1984.  The 
participants at that workshop were Hal Abelson (MIT), Norman 
Adams (Yale), David Bartley (Texas Instruments), Gary Brooks, 
(Texas Instruments, Indiana University), William Clinger 
(Indiana University), Dan Friedman (Indiana University), Robert 
Halstead (MIT), Chris Hanson (MIT), Chris Haynes (Indiana 
University), Eugene Kohlbecker (Indiana University), Don Oxley 
(Texas Instruments), Jonathan Rees (MIT), Bill Rozas (MIT), 
Gerald Sussman (MIT), and Mitchell Wand (Indiana University, 
Brandeis).  Kent Pitman (MIT) made valuable contributions to the 
agenda for the workshop but was unable to attend the sessions.  

We would like also to thank the following people for their 
comments and criticisms in the months following the workshop: 
Kent Dybvig, Andy Freeman, Yekta Gursel, Paul Hudak, Chris 
Lindblad, Guy Steele Jr.  

We thank Dan Friedman and Chris Haynes for permission to use 
text from the Scheme 311 Version 4 reference manual.  We 
acknowledge the influence of manuals for MIT Scheme, T, Scheme 
84, and Common Lisp.  
!Part I: Introduction to Scheme 


I.0 Brief history of Scheme 

Scheme is a programming language invented by Guy Lewis Steele Jr 
and Gerald Jay Sussman.  It is a statically scoped dialect of 
Lisp with an exceptionally clear and simple semantics.  

The first description of Scheme was written in 1975 [\ref].  A 
Revised Report [\ref] appeared in 1978, which described the 
evolution of the language as its MIT implementation was upgraded 
to support an innovative compiler [\ref].  Three distinct 
projects began in 1981 and 1982 to use variants of Scheme for 
courses at MIT, Yale, and Indiana University [\ref, ref, ref].  
An excellent introductory computer science textbook using Scheme 
was published in 1984 [\ref].  

As might be expected of a language used primarily for education 
and research, Scheme has always evolved rapidly.  This was no 
problem when Scheme was used only within MIT, but as Scheme 
became more widespread local subdialects began to diverge until 
students and researchers occasionally found it difficult to 
understand code written at other sites.  Fifteen representatives 
of the major implementations of Scheme therefore met in October 
1984 to work toward a better and more widely accepted standard 
for Scheme.  This paper reports their unanimous recommendations 
augmented by committee work in the areas of input/output and 
arithmetic.  

Scheme shares with Common Lisp [\ref] the goal of a core 
language common to several implementations.  Scheme differs from 
Common Lisp in that the purpose of the common language has as 
much to do with porting ideas as with porting code.  It is 
appropriate therefore that Scheme is much smaller, is less 
pervasively specified, and will evolve faster than Common Lisp.  

!I.1 Syntax 

Formal definitions of the lexical and context-free syntaxes of 
Scheme will be added as appendices.  

Identifiers 

Most identifiers allowed by other programming languages are also 
acceptable to Scheme.  The precise rules for forming identifiers 
vary among implementations of Scheme, but in all implementations 
a sequence of characters that contains no special characters and 
begins with a character that cannot begin a number is an 
identifier.  There may be other identifiers as well, and in 
particular the following are identifiers: 

			   + - 1+ -1+

It is guaranteed that the following characters cannot begin a 
number, so identifiers other than the four listed above should 
begin with one of: 

       a b c d e f g h i j k l m n o p q r s t u v w x y z
       A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
		     ! $ % & * / : < = > ? ~

Subsequent characters of the identifier should be drawn from: 

       a b c d e f g h i j k l m n o p q r s t u v w x y z
       A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
		       0 1 2 3 4 5 6 7 8 9
		  ! $ % & * / : < = > ? ↑ ← . ~

The case in which the letters of an identifier are typed is 
immaterial.  For example, Foo is the same identifier as FOO.  

The following characters are special, and should never be used 
in an identifier: 

                      ) ( ] [ } { " ; blank

Scheme deliberately does not specify whether the following 
characters can be used in identifiers: 

			  # ' ` , @ \ |

Rationale: Some implementations might want to use backwhack ( \) 
and vertical bar ( | ) as in Common Lisp.  As for the others 
there are two schools of thought.  One school argues that 
disallowing special characters in identifiers allows the 
computer to catch more typing errors.  The other school agrees 
only for special characters that come in pairs, because errors 
that involve only the unpaired special characters are easy to 
see.  


Numbers 

For a description of the notations used for numbers, see section 
II.7.  A concise summary of the notations used to write numbers 
will be added to this section, and a formal description will be 
part of the appendix on lexical syntax.  


Comments 

A semicolon indicates the start of a comment.  The comment 
continues to the end of the line on which the semicolon appears.  
Comments are invisible to Scheme, but the end of the line is 
visible as whitespace.  This prevents a comment from appearing 
in the middle of an identifier or number.  Comments may appear 
inside a string that extends over more than one line, but it is 
probably a bad idea to write such strings because their contents 
are implementation-dependent.  


Other notations 

Left and right parentheses are used for grouping and to notate 
lists as described in section II.4.  Left and right square 
brackets and curly braces are not used in Scheme right now but 
are reserved for unspecified future uses.  

The quote (') and backquote (`) characters are used to indicate 
constant or almost-constant data as described in section II.1.  
The comma is used together with the backquote, and the atsign 
(@) is used together with the comma.  

The doublequote character is used to notate strings as described 
in section II.8.  

The sharp sign (octathorp) is used for a variety of purposes 
depending on the character that follows it.  A sharp sign 
followed by a left parenthesis signals the beginning of a 
vector, as described in section II.9.  A sharp sign followed by 
an exclamation point is used to notate one of the special values 
#!true, #!false, and #!null.  A sharp sign followed by a 
backslash is used to notate characters as described in section 
II.8.  A sharp sign followed by any of a number of letters is 
used to notate numbers as described in section II.7.  


Context free grammar for Scheme 

The following grammar is ambiguous because a <special form> 
looks like a <procedure call>.  Some implementations resolve the 
ambiguity by reserving the identifiers that serve as keywords of 
special forms, while other implementations allow the keyword 
meaning of an identifier to be shadowed by lexical bindings.  

    <expression>  ::=  <constant>
                    |  <identifier>
                    |  <special form>
                    |  <procedure call>

    <constant>  ::=  <numeral>  |  #!true  |  #!false  |  #!null
                  |  (quote <datum>)  |  '<datum>

    <special form>  ::=  (<keyword> ...)

    <procedure call>  ::=  (<expression> <arguments>)

    <arguments>  ::=  <empty>  |  <expression> <arguments>

<datum> stands for any written representation of a Scheme 
object, as described in the sections that follow.  <identifier> 
and <numeral> have already been described informally.  <special 
form> stands for one of the special forms whose syntax is 
described in section II.1.  For uniformity the other kinds of 
expressions are also described in that section as though they 
were special forms.  
!I.2 Semantics 


The formal semantics of Scheme will be the subject of an 
appendix to be added.  The detailed informal semantics of Scheme 
is the subject of Part II.  This section gives a quick review of 
Scheme's major characteristics.  

Scheme is a statically scoped programming language, meaning that 
each use of an identifier is associated with a lexically 
apparent binding of that identifier.  In this respect Scheme is 
like Algol 60, Pascal, and C but unlike dynamically scoped 
languages such as APL and traditional Lisp.  

Scheme has latent as opposed to manifest types, which means that 
types are associated with values (also called objects) rather 
than with variables.  (Some authors refer to languages with 
latent types as weakly typed or dynamically typed languages.) 
Other languages with latent types are APL, Snobol, and other 
dialects of Lisp.  Languages with manifest types (sometimes 
referred to as strongly typed or statically typed languages) 
include Algol 60, Pascal, and C.  

All objects created in the course of a Scheme computation, 
including all procedures and variables, have unlimited extent.  
This means in effect that no Scheme object is ever destroyed.  
The reason that implementations of Scheme do not (usually!) run 
out of storage is that they are permitted to reclaim the storage 
occupied by an object if they can prove mathematically that the 
object cannot possibly matter to any future computation.  Scheme 
is a practical programming language only because there exist 
fairly efficient "garbage collection" algorithms for performing 
these proofs.  Other languages in which most objects have 
unlimited extent include APL and Common Lisp.  

Scheme procedures are objects in their own right.  Procedures 
can be created dynamically, stored in data structures, returned 
as results of procedures, and so on.  Other languages with these 
properties include Common Lisp, ML, and KRC.  

Arguments to Scheme procedures are always passed by value, which 
means that the actual argument expressions are evaluated before 
the procedure actually gains control, whether the procedure 
needs the result of the evaluation or not.  ML, C, and APL are 
three good examples of other languages that always pass 
arguments by value.  KRC is a good example of a language that 
passes arguments by name, so that an argument expression is 
evaluated only if its value is needed by the procedure.  
!Part II: A catalog of Scheme 


II.0 Notational conventions 


This part of the report is a catalog of the special forms and 
procedures that make up Scheme.  The special forms are described 
in section II.1, and the procedures are described in the 
following sections.  Each section is organized into entries, 
with one entry (usually) for each special form or procedure.  
Each entry begins with a header line that includes the name of 
the special form or procedure in bold face type within a 
template for the special form or a call to the procedure.  The 
names of the arguments to a procedure are italicized, as are the 
syntactic components of a special form.  A notation such as 

                            expr ...

indicates zero or more occurrences of expr, and so 

                         expr1 expr2 ...

indicates at least one expr.  

At the right of the header line one of the following categories 
will appear: 

                special form
                constant
                variable
                procedure
                essential special form
                essential constant
                essential variable
                essential procedure

A special form is a syntactic class of expressions, usually 
identified by a keyword.  A constant is something that is 
lexically recognizable as a constant.  A variable is an 
identifier that is bound to a location in which values (also 
called objects) can be stored.  Those variables that initially 
hold procedure values are identified as procedures.  

Implementations are free to omit features of Scheme or to add 
extensions, provided the extensions are not in conflict with the 
language reported here.  It is guaranteed, however, that every 
implementation of Scheme will support the essential special 
forms, constants, variables, and procedures.  

Any Scheme value can be used as a boolean expression for the 
purposes of a conditional test.  As explained in section II.2, 
most values count as true, but a few -- notably #!false -- count 
as false.  This manual uses the word "true" to refer to any 
Scheme value that counts as true in a conditional expression, 
and the word "false" to refer to any Scheme value that counts as 
false.  
!II.1.  Special forms 


Identifiers have two uses within Scheme programs.  When an 
identifier appears within a quoted constant (see quote), it is 
being used as data as described in the section on symbols.  
Otherwise it is being used as a name.  There are two kinds of 
things that an identifier can name in Scheme: special forms and 
variables.  A special form is a syntactic class of expressions, 
and an identifier that names a special form is called the 
keyword of that special form.  A variable, on the other hand, is 
a location where a value can be stored.  An identifier that 
names a variable is said to be bound to that location.  The set 
of all such bindings in effect at some point in a program is 
known as the environment in effect at that point.  

Certain special forms are used to allocate storage for new 
variables and to bind identifiers to those new variables.  The 
most fundamental of these binding constructs is the lambda 
special form, because all other binding constructs can be 
explained in terms of lambda expressions.  The other binding 
constructs are the let, let*, letrec, internal definition (see 
define), rec, define!, defrec!, and do special forms.  

Like Algol or Pascal, and unlike most other dialects of Lisp 
except for Common Lisp, Scheme is a statically scoped language 
with block structure.  To each place where an identifier is 
bound in a program there corresponds a region of the program 
within which the binding is effective.  The region varies 
according to the binding construct that establishes the binding; 
if the binding is established by a lambda expression, for 
example, then the region is the entire lambda expression.  Every 
use of an identifier in a variable reference or assignment 
refers to the binding of the identifier that set up the 
innermost of the regions containing the use.  If there is no 
binding of the identifier whose region contains the use, then 
the use refers to the binding for the identifier that was in 
effect when Scheme started up, if any; if there is no binding 
for the identifier, it is said to be unbound.  


variable                                   essential special form

An expression consisting of an identifier that is not the 
keyword of a special form is a variable reference.  The value 
obtained for the variable reference is the value stored in the 
location to which variable is bound.  An error is signalled if 
variable is unbound.  


(procedure arg1 ...)                       essential special form

A list of expressions whose first element is not the keyword of 
a special form indicates a procedure call.  The procedure and 
argument expressions are evaluated and the procedure is passed 
the values of the argument expressions.  In constrast to other 
dialects of Lisp the order of evaluation is not specified, and 
the procedure expression and the argument expressions are always 
evaluated in exactly the same way.  

                (+ 3 4)                 -->  7
                ((if #!false + *) 3 4)  -->  12


(quote constant)                           essential special form 
'constant                                  essential special form

Evaluates to constant.  This notation is used to include literal 
constants in Scheme code.  

                (quote a)               -->  a
                (quote #(a b c))        -->  #(a b c)
                (quote (+ 1 2))         -->  (+ 1 2)

(quote constant) may be abbreviated as 'constant.  The two 
notations are equivalent in all respects.  

                'a                      -->  a
                '#(a b c)               -->  #(a b c)
                '(+ 1 2)                -->  (+ 1 2)
                '(quote a)              -->  (quote a)
                ''a                     -->  (quote a)

Numbers, strings, and the constants #!true, #!false, and #!null 
need not be quoted.  

                '"abc"                  -->  "abc"
                "abc"                   -->  "abc"
                '145932                 -->  145932
                145932                  -->  145932
                '#!true                 -->  #!true
                #!true                  -->  #!true


(lambda (var1 ...) expr)                   essential special form

Each var must be an identifier.  The lambda expression evaluates 
to a procedure with formal argument list (var1 ...) and 
procedure body expr.  The environment in effect when the lambda 
expression was evaluated is remembered as part of the procedure.  
When the procedure is later called with some actual arguments, 
the environment in which the lambda expression was evaluated 
will be extended by binding the identifiers in the formal 
argument list to fresh locations, the corresponding actual 
argument values will be stored in those locations, and expr will 
then be evaluated in the extended environment.  The result of 
expr will be returned as the result of the procedure call.  

        (lambda (x) (+ x x))            -->  #<PROCEDURE>
        ((lambda (x) (+ x x)) 4)        -->  8
        
        (define reverse-subtract
          (lambda (x y) (- y x)))       -->  reverse-subtract
        (reverse-subtract 7 10)         -->  3
        
        (define foo
          (let ((x 4))
            (lambda (y) (+ x y))))      -->  foo
        (foo 6)                         -->  10


(lambda (var1 ...) expr1 expr2 ...)        essential special form

Equivalent to (lambda (var1 ...) (begin expr1 expr2 ...)).  


(lambda var expr1 expr2 ...)               essential special form

Returns a procedure that when later called with some arguments 
will bind var to a fresh location, convert the sequence of 
actual arguments into a list, and store that list in the binding 
of var.  

        ((lambda x x) 3 4 5 6)          -->  (3 4 5 6)

One last variation on the formal argument list provides for a 
so-called rest argument.  If a space/dot/space sequence precedes 
the last argument in the formal argument list, then the value 
stored in the binding of the last formal argument will be a list 
of the actual arguments left over after all the other actual 
arguments have been matched up against the formal arguments.  

        ((lambda (x y . z) z) 3 4 5 6)  -->  (5 6)


(if condition consequent alternative)      essential special form
(if condition consequent)                  essential special form

First evaluates condition.  If it yields a true value (see 
section II.2), then consequent is evaluated and its value is 
returned.  Otherwise alternative is evaluated and its value is 
returned.  If no alternative is specified, then the if 
expression is evaluated only for its effect, and the result of 
the expression is unspecified.  

        (if (>? 3 2) 'yes 'no)          -->  yes
        (if (>? 2 3) 'yes 'no)          -->  no
        (if (>? 3 2) (- 3 2) (+ 3 2))   -->  1


(cond clause1 clause2 ...)                 essential special form

Each clause must be a list of one or more expressions.  The 
first expression in each clause is a boolean expression that 
serves as the guard for the clause.  The guards are evaluated in 
order until one of them evaluates to a true value (see section 
II.2).  When a guard evaluates true, then the remaining 
expressions in its clause are evaluated in order, and the result 
of the last expression in the selected clause is returned as the 
result of the entire expression.  If the selected clause 
contains only the guard, then the value of the guard is returned 
as the result.  If all tests evaluate to false values, then the 
result of the conditional expression is unspecified.  

        (cond ((>? 3 2) 'greater)
              ((<? 3 2) 'less))         --> greater

The special keyword else may be used as a guard to obtain the 
effect of an otherwise clause.  

        (cond ((>? 3 3) 'greater)
              ((<? 3 3) 'less)
              (else 'equal))            -->  equal

The above forms for the clauses are essential.  Some 
implementations support yet another form of clause such that 

        (cond (form1 => form2) ...)

is equivalent to 

        (let ((form1←result form1)
              (thunk2 (lambda () form2))
              (thunk3 (lambda () (cond ...))))
          (if form1←result
              ((thunk2) form1←result)
              (thunk3)))


(case expr clause1 clause2 ...)                      special form

Each clause is a list whose first element is a selector followed 
by one or more expressions.  Each selector should be a list of 
values.  The selectors are not evaluated.  Instead expr is 
evaluated and its result is compared against successive 
selectors using the memv procedure until a match is found.  Then 
the expressions in the selected clause are evaluated from left 
to right and the result of the last expression in the clause is 
returned as the result of the case expression.  If no selector 
matches then the result of the case expression is unspecified.  

        (case (* 2 3)
          ((2 3 5 7) 'prime)
          ((1 4 6 8 9) 'composite))     -->  composite
        (case (car '(c d))
          ((a) 'a)
          ((b) 'b))                     -->  unspecified

The special keyword else may be used as a selector to obtain the 
effect of an otherwise clause.  

        (case (car '(c d))
          ((a e i o u) 'vowel)
          ((y) 'y)
          (else 'consonant))            -->  consonant


(and expr1 ...)                                      special form

Evaluates the exprs from left to right, returning false as soon 
as one evaluates to a false value (see section II.2).  Any 
remaining expressions are not evaluated.  If all the expressions 
evaluate to true values, the value of the last expression is 
returned.  

        (and (=? 2 2) (>? 2 1))         -->  #!true
        (and (=? 2 2) (<? 2 1))         -->  #!false
        (and 1 2 'c '(f g))             -->  (f g)


(or expr1 ...)                                       special form

Evaluates the exprs from left to right, returning the value of 
the first expr that evaluates to a true value (see section 
II.2).  Any remaining expressions are not evaluated.  If all 
expressions evaluate to false values, false is returned.  

        (or (=? 2 2) (>? 2 1))          -->  #!true
        (or (=? 2 2) (<? 2 1))          -->  #!true
        (or #!false #!false #!false)    -->  #!false
        (or (memq 'b '(a b c)) (/ 3 0)) -->  (b c)


(let ((var1 form1) ...) expr1 expr2 ...)   essential special form

Evaluates the forms in the current environment (in some 
unspecified order), binds the vars to fresh locations holding 
the results, and then evaluates the exprs in the extended 
environment, returning the value of the last one.  Each binding 
of a var has expr1 expr2 ...  as its region.  

        (let ((x 2)
              (y 3))
          (* x y))                      -->  6

        (let ((x 2)
              (y 3))
          (let ((foo (lambda (z)
                       (+ x y z)))
                (x 7))
            (foo 4)))                   -->  9

let and letrec give Scheme a block structure.  The difference 
between let and letrec is that in a let the forms are not within 
the regions of the vars being bound.  See letrec.  

Some implementations of Scheme permit a "named let" syntax in 
which 

    (let name ((var1 form1) ...) expr1 expr2 ...)

is equivalent to 

    ((rec name (lambda (id1 ...) expr1 expr2 ...))
     form1 ...)


(let* ((var1 form1) ...) expr1 expr2 ...)            special form

Similar to let, but the bindings are performed sequentially from 
left to right and the region of a binding indicated by (var 
form) is that part of the let* expression to the right of the 
binding.  Thus the second binding is done in an environment in 
which the first binding is visible, and so on.  


(letrec ((var1 form1) ...) expr1 expr2 ...)essential special form

Binds the vars to fresh locations holding undefined values, 
evaluates the forms in the resulting environment (in some 
unspecified order), assigns to each var the result of the 
corresponding form, evaluates the exprs sequentially in the 
resulting environment, and returns the value of the last expr.  
Each binding of a var has the entire letrec expression as its 
region, making it possible to define mutually recursive 
procedures.  See let.  

        (letrec ((x 2)
                 (y 3))
          (letrec ((foo (lambda (z)
                          (+ x y z)))
                   (x 7))
            (foo 4)))                   -->  14

        (letrec  ((even? (lambda (n)
                           (if (zero? n)
                               #!true
                               (odd? (-1+ n)))))
                  (odd? (lambda (n)
                          (if (zero? n)
                              #!false
                              (even? (-1+ n))))))
          (even? 88))
                                        -->  #!true

One restriction on letrec is very important: it must be possible 
to evaluate each form without referring to the value of a var.  
If this restriction is violated, then the effect is undefined, 
and an error may be signalled during evaluation of the forms.  
The restriction is necessary because Scheme uses call by value 
rather than call by name.  In the most common uses of letrec, 
all the forms are lambda expressions and the restriction is 
satisfied automatically.  

                  
(rec var expr)                                       special form

Equivalent to (letrec ((var expr)) var).  rec is useful for 
defining self-recursive procedures.  


(named-lambda (name var1 ...) expr ...)              special form

Equivalent to 

        (rec name (lambda (var1 ...) expr ...))

Rationale: Some implementatations may find it easier to provide 
good debugging information when named-lambda is used instead of 
rec.  


(define var expr)                          essential special form

When typed at top level (so that it is not nested within any 
other expression), this form has essentially the same effect as 
(set! var expr) if var is bound.  If var is not bound, however, 
then the define form will bind var before performing the 
assignment, whereas it would be an error to perform a set! on an 
unbound identifier.  The value returned by a define form is not 
specified.  

    (define add3 (lambda (x) (+ x 3)))  -->  unspecified
    (add3 3)                            -->  6
    (define first car)                  -->  unspecified
    (first '(1 2))                      -->  1

The semantics just described is essential.  Some implementations 
also allow define expressions to appear at the beginning of the 
body of a lambda, named-lambda, let, let*, or letrec expression.  
Such expressions are known as internal definitions as opposed to 
the top level definitions described above.  The variable defined 
by an internal definition is local to the body of the lambda, 
named-lambda, let, let*, or letrec expression.  That is, var is 
bound rather than assigned, and the region set up by the binding 
is the entire body of the lambda, named-lambda, let, let*, or 
letrec expression.  For example, 

        (let ((x 5))
          (define foo
            (lambda (y)
              (bar x y)))
          (define bar
            (lambda (a b)
              (+ (* a b) a)))
          (foo (+ x 3)))                -->  45

Internal definitions can always be converted into an equivalent 
letrec expression.  For example, the let expression in the above 
example is equivalent to 

            (let ((x 5))
              (letrec ((foo (lambda (y)
                              (bar x y)))
                       (bar (lambda (a b)
                              (+ (* a b) a))))
                (foo (+ x 3))))


(define (var0 var1 ...) expr1 expr2 ...)             special form
(define (form var1 ...) expr1 expr2 ...)             special form

The first form, where var0 is an identifier, is equivalent to 

  (define var0 (rec var0 (lambda (var1 ...) expr1 expr2 ...))).

The second form, where form is a list, is sometimes convenient 
for defining a procedure that returns another procedure as its 
result.  It is equivalent to 

  (define form (lambda (var1 ...) expr1 expr2 ...)).


(define! var expr)                                   special form

If var is bound, then the define! form is equivalent to the 
corresponding set!.  If var is unbound, however, define! binds 
var in the global environment before performing the assignment.  


Rationale: This makes sense only for implementations with a 
distinguished global environment.  


(defrec! var expr)                                   special form

Equivalent to (define! var (rec var expr)).  


(set! var expr)                            essential special form

Stores the value of expr in the location to which var is bound.  
expr is evaluated but var is not.  The result of the set! 
expression is unspecified.  

                (set! x 4)              -->  unspecified
                (1+ x)                  -->  5

Rationale: set! expressions are Scheme's assignment statements.  
Assignment statements are seldom used in good Scheme code.  
Their major uses are to initialize variables accessed 
interactively and to construct objects with local state.  


(begin expr1 expr2 ...)                    essential special form

Evaluates the exprs sequentially from left to right and returns 
the value of the last expr.  Used to sequence side effects such 
as input and output.  

        (begin (set! x 5)
               (1+ x))                  -->  6
Also 
        (begin (display "4 plus 1 equals ")
               (display (1+ 4)))
prints 
                        4 plus 1 equals 5

A number of special forms such as lambda and letrec implicitly 
treat their bodies as begin expressions.  


(sequence expr1 expr2 ...)                           special form

sequence is synonymous with begin.  

Rationale: sequence was used in the Abelson and Sussman text, 
but it should not be used in new code.  


(do ((var1 init1 step1) ...)                         special form
    (test expr1 ...)
    stmt1 ...)

The do special form is an extremely general albeit complex 
iteration macro.  Each var must be an identifier and each init 
and step must be expressions.  The init expressions are 
evaluated (in some unspecified order), the vars are bound to 
fresh locations, the results of the init expressions are stored 
in the bindings of the vars, and then the iteration phase 
begins.  

Each iteration begins by evaluating test; if the result is false 
(see section II.2), then the stmts are evaluated in order for 
effect, the steps are evaluated (in some unspecified order), the 
results of the step expressions are stored in the bindings of 
the vars, and the next iteration begins.  

If test evaluates true, then the exprs are evaluated from left 
to right and the value of the last expr is returned as the value 
of the do expression.  If no exprs are present, then the value 
of the do expression is unspecified.  

The region set up by the binding of a var consists of the entire 
do expression except for the inits.  

A step may be omitted, in which case the corresponding var is 
not updated.  When the step is omitted the init may be omitted 
as well, in which case the initial value is not specified.  

    (do ((vec (make-vector 5))
         (i 0 (1+ i)))
        ((=? i 5) vec)
        (vector-set! vec i i))          -->  #(0 1 2 3 4)

    (let ((x '(1 3 5 7 9)))
      (do ((x x (cdr x))
           (sum 0 (+ sum (car x))))
          ((null? x) sum)))             -->  25

The do special form is essentially the same as the do macro in 
Common Lisp.  The main difference is that in Scheme the 
identifier return is not bound; programmers that want to bind 
return as in Common Lisp must do so explicitly (see 
call-with-current-continuation).  


`pattern                                       macro special form

The backquote special form is useful for constructing a list 
structure when most but not all of the desired structure is 
known in advance.  If no commas appear within the pattern, the 
result of evaluating `pattern is equivalent (in the sense of 
equal?) to the result of evaluating 'pattern.  If a comma 
appears within the pattern, however, the expression following 
the comma is evaluated and its result is inserted into the 
structure instead of the comma and the expression.  If a comma 
appears followed immediately by an at-sign (@), then the 
following expression must evaluate to a list; the opening and 
closing parentheses of the list are then "stripped away" and the 
elements of the list are inserted in place of the 
comma/at-sign/expression sequence.  

  `(a ,(+ 1 2) ,@(mapcar 1+ '(4 5 6)) b)  -->  (a 3 5 6 7 b)
  `(((foo ,(- 10 3)) ,@(cdr '(c)) cons))  -->  (((foo 7) cons))


Scheme does not have any standard facility for defining new 
special forms.  

Rationale: The ability to define new special forms creates 
numerous problems.  All current implementations of Scheme have 
macro facilities that solve those problems to one degree or 
another, but the solutions are quite different and it isn't 
clear at this time which solution is best, or indeed whether any 
of the solutions are truly adequate.  Rather than standardize, 
we are encouraging implementations to continue to experiment 
with different solutions.  

The main problems with traditional macros are: They must be 
defined to the system before any code using them is loaded; this 
is a common source of obscure bugs.  They are usually global; 
macros can be made to follow lexical scope rules as in Common 
Lisp's macrolet, but many people find the resulting scope rules 
confusing.  Unless they are written very carefully, macros are 
vulnerable to inadvertant capture of free variables; to get 
around this, for example, macros may have to generate code in 
which procedure values appear as quoted constants.  There is a 
similar problem with keywords if the keywords of special forms 
are not reserved.  If keywords are reserved, then either macros 
introduce new reserved words, invalidating old code, or else 
special forms defined by the programmer do not have the same 
status as special forms defined by the system.  
!II.2.  Booleans 


The standard boolean objects for truth and falsity are written 
as #!true and #!false.  What really matters, though, are the 
objects that the Scheme conditional expressions (if, cond, and, 
or, do) will treat as though they were true or false.  The 
phrase "a true value" (or sometimes just "true") means any 
object treated as true by the conditional expressions, and the 
phrase "a false value" (or "false") means any object treated as 
false by the conditional expressions.  

Of all the standard Scheme values, only #!false and the empty 
list count as false in conditional expressions.  #!true, pairs 
(and therefore lists), symbols, numbers, strings, vectors, and 
procedures all count as true.  

The empty list counts as false for historical reasons only, and 
programs should not rely on this because future versions of 
Scheme will probably do away with this nonsense.  

Programmers accustomed to other dialects of Lisp should beware 
that Scheme has already done away with the nonsense that 
identifies the empty list with the symbol nil.  


#!false                                        essential constant

#!false is the boolean value for falsity.  The #!false object is 
self-evaluating.  That is, it does not need to be quoted in 
programs.  

                        '#!false        -->  #!false
                        #!false         -->  #!false


#!true                                         essential constant

#!true is the boolean value for truth.  The #!true object is 
self-evaluating, and does not need to be quoted in programs.  


(not obj)                                     essential procedure

Returns #!true if obj is false and returns #!false otherwise.  


nil                                                      variable
t                                                        variable

As a crutch for programmers accustomed to other dialects of 
Lisp, some implementations provide variables nil and t whose 
initial values are #!false and #!true respectively.  These 
variables should not be used in new code.  
!II.3.  Equivalence predicates 


A predicate is a procedure that always returns #!true or 
#!false.  Of the equivalence predicates described in this 
section, eq? is the most discriminating while equal? is the most 
liberal.  eqv? is very slightly less discriminating than eq?.  


(eq? obj1 obj2)                               essential procedure

Returns #!true if obj1 is identical in all respects to obj2, 
otherwise returns #!false.  If there is any way at all that a 

∂19-Mar-85  0505	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 2
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  05:04:57 PST
Received: from CSNET-SH by MIT-MC.ARPA; 19 MAR 85 07:56:39 EST
To: scheme@MIT-MC.ARPA
Subject: Message a011267 LONG message - part 2
Reply-to: cic@CSNET-SH.ARPA
Date: 19 Mar 85 07:51:18 EST (Tue)
From: "Charlotte D. Mooers" <postmaster@CSNET-SH.ARPA>


user can distinguish obj1 and obj2, then eq? will return 
#!false.  On the other hand, it is guaranteed that objects 
maintain their identity despite being fetched from or stored 
into variables or data structures.  

The notion of identity used by eq? is stronger than the notions 
of equivalence used by the eqv? and equal? predicates.  The 
constants #!true and #!false are identical to themselves and are 
different from everything else, except that in some 
implementations the empty list is identical to #!false for 
historical reasons.  Two symbols are identical if they print the 
same way (except that some implementations may have "uninterned 
symbols" that violate this rule).  For structured objects such 
as pairs and vectors the notion of sameness is defined in terms 
of the primitive mutation procedures defined on those objects.  
For example, two pairs are the same if and only if a set-car! 
operation on one changes the car field of the other.  The rules 
for identity of numbers are extremely implementation-dependent 
and should not be relied on.  

Generally speaking, the equal? procedure should be used to 
compare lists, vectors, and arrays.  The string-equal? procedure 
should be used to compare strings, and the =? procedure should 
be used to compare numbers.  The eqv? procedure is just like eq? 
except that it is more inclined to say that two numbers are the 
same.  

        (eq? 'a 'a)                     -->  #!true
        (eq? 'a 'b)                     -->  #!false
        (eq? '(a) '(a))                 -->  unspecified
        (eq? "a" "a")                   -->  unspecified
        (eq? 2 2)                       -->  unspecified
        (eq? (cons 'a 'b) (cons 'a 'b)) -->  #!false
        (let ((x (read)))
          (eq? (cdr (cons 'b x)) x)))   -->  #!true


(eqv? obj1 obj2)                              essential procedure

eqv? is just like eq? except that if obj1 and obj2 are exact 
numbers then eqv? is guaranteed to return #!true if obj1 and 
obj2 are equal according to the =? procedure.  

                (eq? 100000 100000)     -->  unspecified
                (eqv? 100000 100000)    -->  #!true

See section II.6 for a discussion of exact numbers.  


(equal? obj1 obj2)                            essential procedure

Returns #!true if obj1 and obj2 are identical objects or if they 
are equivalent numbers, lists, strings, vectors, or arrays.  Two 
objects are generally considered equivalent if they print the 
same.  equal? may not terminate if its arguments are circular 
data structures.  

        (equal? 'a 'a)                  -->  #!true
        (equal? '(a) '(a))              -->  #!true
        (equal? '(a (b) c) '(a (b) c))  -->  #!true
        (equal? "abc" "abc")            -->  #!true
        (equal? 2 2)                    -->  #!true
        (equal? (make-vector 5 'a)
                (make-vector 5 'a))     -->  #!true

equal? is a blunderbuss of a predicate and should not be used 
when a less liberal or more specific predicate will suffice.  
!II.4.  Pairs and lists 


Lists are Lisp's -- and therefore Scheme's -- characteristic 
data structures.  Even Lisp and Scheme programs are lists.  

The empty list is a special object that is written as an opening 
parenthesis followed by a closing parenthesis: 

                               ()

The empty list has no elements, and its length is zero.  The 
empty list is not a pair.  

Larger lists are built out of pairs.  A pair (sometimes called a 
"dotted pair") is a record structure with two fields called the 
car and cdr fields (for historical reasons).  Pairs are created 
by the constructor procedure cons.  The car and cdr fields are 
accessed by the selector procedures car and cdr.  The car and 
cdr fields are assigned by the mutator procedures set-car! and 
set-cdr!.  

The most general notation used for Scheme pairs is the "dotted" 
notation (c1 .  c2) where c1 is the value of the car field and 
c2 is the value of the cdr field.  For example 

                        (4 . 5)

is a pair whose car is 4 and whose cdr is 5.  

The dotted notation is not often used, because more streamlined 
notations exist for the common case where the cdr is the empty 
list or a pair.  (c1 .  ()) is usually written as (c1).  (c1 .  
(c2 .  c3)) is usually written as (c1 c2 .  c3).  Usually these 
special notations permit a structure to be written without any 
dotted pair notation at all.  For example 

                (a . (b . (c . (d . (e . ())))))

would normally be written as                                     

                        (a b c d e)

When all the dots can be made to disappear as in the example 
above, the entire structure is called a proper list.  Proper 
lists are so common that when people speak of a list, they 
usually mean a proper list.  For those who prefer an inductive 
definition: 

        1.  The empty list is a proper list.
        2.  If l is a proper list, then any pair whose cdr is 
            l is also a proper list.
        3.  There are no other proper lists.

A proper list is therefore either the empty list or a pair from 
which the empty list can be obtained by applying the cdr 
procedure a finite number of times.  

Whether a given pair is a proper list depends upon what is 
stored in the cdr field.  When the set-cdr! procedure is used, 
an object can be a proper list one moment and not the next: 

                (define x '(a b c))     -->  x
                (define y x)            -->  y
                (set-cdr! x 4)          -->  unspecified
                x                       -->  (a . 4)
                (eq? x y)               -->  #!true
                y                       -->  (a . 4)

A pair object, on the other hand, will always be a pair object.  


It is often convenient to speak of a homogeneous (proper) list 
of objects of some particular data type, as for example (1 2 3) 
is a list of integers.  To be more precise, suppose D is some 
data type.  (Any predicate defines a data type consisting of 
those objects of which the predicate is true.) Then 

        1.  The empty list is a list of D.
        2.  If l is a list of D, then any pair
            whose cdr is l and whose car satisfies the data
            type D is also a list of D. 
        3.  There are no other lists of D.


(pair? obj)                                   essential procedure

Returns #!true if obj is a pair, otherwise returns #!false.  

                (pair? '(a . b))        -->  #!true
                (pair? '(a b c))        -->  #!true
                (pair? '())             -->  #!false
                (pair? '#(a b))         -->  #!false


(cons obj1 obj2)                              essential procedure

Returns a newly allocated pair whose car is obj1 and whose cdr 
is obj2.  The pair is guaranteed to be different (in the sense 
of eq?) from every existing object.  

                (cons 'a '())           -->  (a)
                (cons '(a) '(b c d))    -->  ((a) b c d)
                (cons "a" '(b c))       -->  ("a" b c)
                (cons 'a 3)             -->  (a . 3)
                (cons '(a b) 'c)        -->  ((a b) . c)


(car pair)                                    essential procedure

Returns the contents of the car field of pair.  pair must be a 
pair.  Note that taking the car of the empty list is an error.  

                (car '(a b c))          -->  a
                (car '((a) b c d))      -->  (a)
                (car '(1 . 2))          -->  1
                (car '())               -->  error


(cdr pair)                                    essential procedure

Returns the contents of the cdr field of pair.  pair must be a 
pair.  Note that taking the cdr of the empty list is an error.  

                (cdr '((a) b c d))      -->  (b c d)
                (cdr '(1 . 2))          -->  2
                (cdr '())               -->  error


(set-car! pair obj)                           essential procedure

Stores obj in the car field of pair.  pair must be a pair.  The 
value returned by set-car! is unspecified.  This procedure can 
be very confusing if used indiscriminately.  


(set-cdr! pair obj)                           essential procedure

Stores obj in the cdr field of pair.  pair must be a pair.  The 
value returned by set-cdr! is unspecified.  This procedure can 
be very confusing if used indiscriminately.  


(caar pair)                                   essential procedure
(cadr pair)                                   essential procedure
(cdar pair)                                   essential procedure
(cddr pair)                                   essential procedure
(caaar pair)                                  essential procedure
(caadr pair)                                  essential procedure
(cadar pair)                                  essential procedure
(caddr pair)                                  essential procedure
(cdaar pair)                                  essential procedure
(cdadr pair)                                  essential procedure
(cddar pair)                                  essential procedure
(cdddr pair)                                  essential procedure
(caaaar pair)                                 essential procedure
(caaadr pair)                                 essential procedure
(caadar pair)                                 essential procedure
(caaddr pair)                                 essential procedure
(cadaar pair)                                 essential procedure
(cadadr pair)                                 essential procedure
(caddar pair)                                 essential procedure
(cadddr pair)                                 essential procedure
(cdaaar pair)                                 essential procedure
(cdaadr pair)                                 essential procedure
(cdadar pair)                                 essential procedure
(cdaddr pair)                                 essential procedure
(cddaar pair)                                 essential procedure
(cddadr pair)                                 essential procedure
(cdddar pair)                                 essential procedure
(cddddr pair)                                 essential procedure

These procedures are compositions of car and cdr, where for 
example caddr could be defined by 

        (define caddr (lambda (x) (car (cdr (cdr x)))))


'()                                            essential constant
#!null                                                   constant

() is the empty list.  The #!null notation does not have to be 
quoted in programs.  The '() notation must include the quote, 
however, because otherwise it would be a procedure call without 
a procedure expression.  

Rationale: Because many current Scheme interpreters deal with 
expressions as list structures rather than as character strings, 
they will treat an unquoted () as though it were quoted.  It is 
entirely possible, however, that some implementations of Scheme 
will be able to detect this error.  


(null? obj)                                   essential procedure

Returns #!true if obj is the empty list, otherwise returns 
#!false.  


(list obj1 ...)                               essential procedure

Returns a list of its arguments.  

        (list 'a (+ 3 4) 'c)            -->  (a 7 c)


(length plist)                                essential procedure

Returns the length of plist, which must be a proper list.  

        (length '())                    -->  0
        (length '(a b c))               -->  3
        (length '(a (b) (c d e)))       -->  3


(append plist1 plist2)                        essential procedure
(append plist ...)                                      procedure

Returns a list consisting of the elements of the first plist 
followed by the elements of the other plists.  All plists should 
be proper lists.  

        (append '(x) '(y))              -->  (x y)
        (append '(a) '(b c d))          -->  (a b c d)
        (append '(a (b)) '((c)))        -->  (a (b) (c))


(append! plist ...)                                     procedure

Like append but may side effect its arguments.  


(reverse plist)                                         procedure

Returns a list consisting of the elements of plist in reverse 
order.  plist must be a proper list.  

        (reverse '(a b c))              -->  (c b a)
        (reverse '(a (b c) d (e (f))))  -->  ((e (f)) d (b c) a)


(list-ref x n)                                          procedure

Returns the car of (list-tail x n).  


(list-tail x n)                                         procedure

Returns the sublist of x obtained by omitting the first n 
elements.  Could be defined by 

        (define list-tail
          (lambda (x n)
            (if (zero? n)
                x
                (list-tail (cdr x) (- n 1)))))


(last-pair x)                                           procedure

Returns the last pair in the nonempty list x.  Could be defined 
by 

        (define last-pair
          (lambda (x)
            (if (pair? (cdr x))
                (last-pair (cdr x))
                x)))


(memq obj plist)                              essential procedure
(memv obj plist)                              essential procedure
(member obj plist)                            essential procedure

Finds the first occurrence of obj in the proper list plist and 
returns the first sublist of plist beginning with obj.  If obj 
does not occur in plist, returns #!false.  memq uses eq? to 
compare obj with the elements of plist, while memv uses eqv? and 
member uses equal?.  

        (memq 'a '(a b c))              -->  (a b c)
        (memq 'b '(a b c))              -->  (b c)
        (memq 'a '(b c d))              -->  #!false
        (memq (list 'a) '(b (a) c))     -->  #!false
        (memq 101 '(100 101 102))       -->  unspecified
        (memv 101 '(100 101 102))       -->  (101 102)
        (member (list 'a) '(b (a) c))   -->  ((a) c)


(assq obj alist)                              essential procedure
(assv obj alist)                              essential procedure
(assoc obj alist)                             essential procedure

alist must be a proper list of pairs.  Finds the first pair in 
alist whose car field is obj and returns that pair.  If no pair 
in alist has obj as its car, returns #!false.  assq uses eq? to 
compare obj with the car fields of the pairs in alist, while 
assv uses eqv? and assoc uses equal?.  

        (assq 'a '((a 1) (b 2) (c 3)))     -->  (a 1)
        (assq 'b '((a 1) (b 2) (c 3)))     -->  (b 2)
        (assq 'd '((a 1) (b 2) (c 3)))     -->  #!false
        (assq '(a) '(((a)) ((b)) ((c))))   -->  #!false
        (assq 5 '((2 3) (5 7) (11 13)))    -->  unspecified
        (assv 5 '((2 3) (5 7) (11 13)))    -->  (5 7)
        (assoc '(a) '(((a)) ((b)) ((c))))   -->  ((a))

Rationale: memq, memv, member, assq, assv, assoc do not have 
question marks in their names because they return useful values 
rather than just #!true.  
!II.5.  Symbols 


Symbols are objects whose usefulness rests entirely on the fact 
that two symbols are identical (in the sense of eq?) if and only 
if their names are spelled the same way.  This is exactly the 
property that is needed for identifiers in programs, and so most 
implementations of Scheme use them internally for that purpose.  
Programmers may also use symbols as they use enumerated types in 
Pascal.  

The rules for writing a symbol are the same as the rules for 
writing an identifier (see section I.2).  As with identifiers, 
different implementations of Scheme use slightly different 
rules, but it is always the case that a sequence of characters 
that contains no special characters and begins with a character 
that cannot begin a number is taken to be a symbol; in addition 
+, -, 1+, and -1+ are symbols.  

The case in which a symbol is written in unimportant.  Some 
implementations of Scheme convert any upper case letters to 
lower case, and others convert lower case to upper case.  

It is guaranteed that any symbol that has been read using the 
read procedure and subsequently written out using the write 
procedure will read back in as the identical symbol (in the 
sense of eq?).  The string->symbol procedure, however, can 
create symbols for which the write/read invariance may not hold 
because their names contain special characters or letters in the 
non-standard case.  

Rationale: Some implementations of Lisp have a feature known as 
"slashification" in order to guarantee write/read invariance for 
all symbols, but historically the most important use of this 
feature has been to compensate for the lack of a string data 
type.  Some implementations have "uninterned symbols", which 
defeat write/read invariance even in implementations with 
slashification and also generate exceptions to the rule that two 
symbols are the same if and only if their names are spelled the 
same.  It is questionable whether these features are worth their 
complexity, so they are not standard in Scheme.  


(symbol? obj)                                 essential procedure

Returns #!true is obj is a symbol, otherwise returns #!false.  

                (symbol? 'foo)          -->  #!true
                (symbol? (car '(a b)))  -->  #!true
                (symbol? "bar")         -->  #!false


(symbol->string symbol)                       essential procedure

Returns the name of symbol as a string.  symbol->string performs 
no case conversion.  See string->symbol.  The following examples 
assume the read procedure converts to lower case: 

        (symbol->string 'flying-fish)   -->  "flying-fish"
        (symbol->string 'Martin)        -->  "martin"
        (symbol->string
          (string->symbol "Malvina"))   -->  "Malvina"


(string->symbol string)                       essential procedure

Returns the symbol whose name is string.  string->symbol can 
create symbols with special symbols or upper case letters in 
their names, but it is usually a bad idea to create such symbols 
because in some implementations of Scheme they cannot be read as 
themselves.  See symbol->string.  

    'mISSISSIppi                        -->  mississippi

    (string->symbol "mISSISSIppi")      -->  mISSISSIppi

    (eq? 'bitBlt
         (string->symbol "bitBlt"))     -->  #!false

    (eq? 'JollyWog
         (string->symbol
           (symbol->string 'JollyWog))) -->  #!true

    (string-equal?
      "K. Harper, M.D."
      (symbol->string
        (string->symbol
          "K. Harper, M.D.")))          -->  #!true


!II.6.  Numbers (part 1) 


Numerical computation has traditionally been neglected by the 
Lisp community.  Until Common Lisp there has been no carefully 
thought out strategy for organizing numerical computation, and 
with the exception of the MacLisp system there has been little 
effort to execute numerical code efficiently.  We applaud the 
excellent work of the Common Lisp committee and we accept many 
of their recommendations.  In some ways we simplify and 
generalize their proposals in a manner consistent with the 
purposes of Scheme.  

Scheme's numerical operations treat numbers as abstract data, as 
independent of the machine representation as is possible.  Thus, 
the casual user should be able to write simple programs without 
having to know that the implementation may use fixed-point, 
floating-point, and perhaps other representations for his data.  
Unfortunately, this illusion of uniformity can only be sustained 
approximately -- the implementation of numbers will leak out of 
our abstraction whenever the user must be in control of 
precision, or accuracy, or when he must construct especially 
efficient computations.  Thus we also must provide escape 
mechanisms so that a sophisticated programmer can exercise more 
control of the execution of his code and the representation of 
his data when it is essential to do so.  

We separate out several apparently related issues of 
representation -- the abstract numbers, their machine 
representation, and the input/output formats of the symbolic 
expressions which denote numerical constants.  We will use 
mathematical words such as NUMBER, COMPLEX, REAL, RATIONAL, and 
INTEGER for properties of the abstract numbers, data-structure 
names such as FIXNUM, BIGNUM, RATNUM, and FLONUM for machine 
representations, and names like INT, FIX, FLO, SCI, RAT, POLAR, 
and RECT for input/output formats.  

Notations for numbers are the subject of section II.7.  


Numbers.  

A Scheme system provides data of type NUMBER, which is the most 
general numerical type supported by that system.  NUMBER is 
likely to be a complicated union type implemented in terms of 
FIXNUMs, BIGNUMS, FLONUMS, etc.  but this should not be apparent 
to a naive user.  What the user sees is that the obvious 
operations on numbers produce the mathematically expected 
results, within the limits of the implementation.  Thus if the 
user divides 3 by 2, he should get something like 1.5 (or, the 
exact fraction 3/2).  If he adds that result to itself, and if 
the implementation can swing it, he should get an exact 3.  

Mathematically, numbers may be arranged into a tower of subtypes 
with natural projections and injections relating adjacent 
members of the tower: 

                                NUMBER
                                COMPLEX
                                REAL
                                RATIONAL
                                INTEGER

We impose a uniform rule of downward coercion -- a number of one 
type is also of a lower type if the injection (up) of the 
projection (down) of a number leaves the number unchanged.  
Since this tower is a real mathematical entity, Scheme provides 
predicates and procedures that access the tower.  

Not all Scheme implementations must provide the whole tower, but 
they are required to implement a coherent subset, consistent 
with the purposes of Scheme.  


Exactness.  

Numbers are either EXACT or INEXACT.  A number is exact if it 
was derived from EXACT numbers using only EXACT operations.  A 
number is INEXACT if it models a quantity known only 
approximately, if it was derived using INEXACT ingredients, or 
if it was derived using INEXACT operations.  Thus INEXACTness is 
a contagious property of a number.  Some operations, such as the 
square root (of non-square numbers) must be INEXACT because of 
the finite precision of our representations.  Other operations 
are inexact because of implementation requirements.  We 
emphasize that exactness is independent of the position of the 
number on the tower.  It is perfectly possible to have an 
INEXACT INTEGER or an EXACT REAL; 355/113 may be an EXACT 
RATIONAL or it may be an INEXACT RATIONAL approximation to pi, 
depending on the application.  

Operationally, it is the system's responsibility to combine 
EXACT numbers using exact methods, such as infinite precision 
integer and rational arithmetic, where possible.  An 
implementation may not be able to do this (if it does not use 
infinite precision integers and rationals), but if a number 
becomes inexact for implementation reasons there is probably an 
important error condition, such as integer overflow, to be 
reported.  Arithmetic on INEXACT numbers is not so constrained.  
The system may use floating point and other flaky representation 
strategies for INEXACT numbers.  This is not to say that 
implementors need not use the best known algorithms for INEXACT 
computations -- only that high-quality approximate methods are 
allowed.  In a system which cannot explicitly distinguish exact 
from inexact numbers the system must do its best to maintain 
precision.  Scheme systems must not burden users with numerical 
operations described in terms of hardware and operating-system 
dependent representations such as FIXNUM and FLONUM.  These 
representation issues should not be germane to the user's 
problems.  

We highly recommend that the IEEE 32-bit and 64-bit 
floating-point standards be adopted for implementations that use 
floating-point internal representations.  To minimize loss of 
precision we adopt the following rules: If an implementation 
uses several different sizes of floating-point formats, the 
results of any operation with a floating-point result must be 
expressed in the largest format used to express any of the 
floating-point arguments to that operation.  It is desirable 
(but not required) for potentially irrational operations such as 
sqrt, when applied to EXACT arguments, to produce EXACT answers 
when that is possible (eg.  sqrt[4]=2, exactly).  If an EXACT 
number (or an INEXACT number represented as a FIXNUM, a BIGNUM, 
or a RATNUM) is operated upon so as to produce an INEXACT result 
(as by sqrt), and if the result is represented as a FLONUM, then 
the largest available format FLONUM must be used; but if the 
result is expressed as a RATNUM then the rational approximation 
must have at least as much precision as the largest available 
format FLONUM.  (Note that this last rule is much stronger than 
that used in Common Lisp.  Consider the result of the square 
root of a rational, for example.) 


Numerical operations.  

Scheme provides the usual set of operations for manipulating 
numbers.  In general, numerical operations require numerical 
arguments.  For succintness we let the following meta-symbols 
range over the indicated types of object in our descriptions, 
and we let these meta-symbols specify the types of the arguments 
to numeric operations.  It is an error for an operation to be 
presented with an argument that it is not specified to handle.  

  obj                    any arbitrary object
  z, z1, ... zi, ...     complex, real, rational, integer
  x, x1, ... xi, ...     real, rational, integer
  q, q1, ... qi, ...     rational, integer
  n, n1, ... ni, ...     integer


(number? obj)                                 essential procedure
(complex? obj)                                essential procedure
(real? obj)                                   essential procedure
(rational? obj)                               essential procedure
(integer? obj)                                essential procedure

These numerical type predicates can be applied to any kind of 
argument.  They return true if the object is of the named type.  
In general, if a type predicate is true of a number then all 
higher type predicates are also true of that number.  Not every 
system supports all of these types; it is entirely possible to 
have a Scheme system that has only INTEGERs.  Nonetheless every 
implementation of Scheme must have all of these predicates.  


(zero? z)                                     essential procedure
(positive? x)                                 essential procedure
(negative? x)                                 essential procedure
(odd? n)                                      essential procedure
(even? n)                                     essential procedure
(exact? z)                                    essential procedure
(inexact? z)                                  essential procedure

These numerical predicates test a number for a particular 
property.  They return a boolean value.  


(= z1 z2)                                     essential procedure
(=? z1 z2)                                    essential procedure
(= z1 z2 z3 ...)                                        procedure
(=? z1 z2 z3 ...)                                       procedure
(< x1 x2)                                     essential procedure
(<? x1 x2)                                    essential procedure
(< x1 x2 x3 ...)                                        procedure
(<? x1 x2 x3 ...)                                       procedure
(> x1 x2)                                     essential procedure
(>? x1 x2)                                    essential procedure
(> x1 x2 x3 ...)                                        procedure
(>? x1 x2 x3 ...)                                       procedure
(<= x1 x2)                                    essential procedure
(<=? x1 x2)                                   essential procedure
(<= x1 x2 x3 ...)                                       procedure
(<=? x1 x2 x3 ...)                                      procedure
(>= x1 x2)                                    essential procedure
(>=? x1 x2)                                   essential procedure
(>= x1 x2 x3 ...)                                       procedure
(>=? x1 x2 x3 ...)                                      procedure

The numerical comparison predicates have redundant names (with 
and without the terminal "?") to make all populations happy.  
They optionally take many arguments, as in Common Lisp, to 
facilitate range checks.  These procedures return true if their 
arguments are (respectively): numerically equal, monotonically 
increasing, monotonically decreasing, monotonically 
nondecreasing, or monotonically nonincreasing.  Warning: On 
INEXACT numbers equality tests will give unreliable results; 
other numerical comparisons are only heuristically useful (ask a 
numerical analyst about this!).  


(max x1 x2)                                   essential procedure
(max x1 x2 ...)                                         procedure
(min x1 x2)                                   essential procedure
(min x1 x2 ...)                                         procedure

Returns the maximum or minimum of its arguments, respectively.  


(+ z1 z2)                                     essential procedure
(+ z1 ...)                                              procedure
(* z1 z2)                                     essential procedure
(* z1 ...)                                              procedure

These procedures return the sum or product of their arguments.  

                (+ 3 4)                 -->  7
                (+ 3)                   -->  3
                (+)                     -->  0
                (* 4)                   -->  4
                (*)                     -->  1


(- z1 z2)                                     essential procedure
(- z1 z2 ...)                                           procedure
(/ z1 z2)                                     essential procedure
(/ z1 z2 ...)                                           procedure

With two or more arguments, these procedures return the 
difference or (complex) quotient of their arguments, associating 
to the left.  With one argument, however, they return the 
additive or multiplicative inverse of their argument.  

                (- 3 4)                 -->  -1
                (- 3 4 5)               -->  -6
                (- 3)                   -->  -3
                (/ 3 4 5)               -->  3/20
                (/ 3)                   -->  1/3


(1+ z)                                                  procedure
(-1+ z)                                                 procedure

These procedures return the result of adding or subtracting 1 to 
their argument.  


(abs z)                                       essential procedure

Returns the magnitude of its argument.  

                (abs -7)                -->  7
                (abs -3+4i)             -->  5


(quotient n1 n2)                              essential procedure
(remainder n1 n2)                             essential procedure
(modulo n1 n2)                                          procedure

In general, these are intended to implement number-theoretic 
(integer) division, where for positive integers n1 and n2 if n3 
and n4 are integers such that 

               n1 = n3 * n2 + n4 and 0 <= n4 < n2

then 

                (quotient n1 n2)        -->  n3
                (remainder n1 n2)       -->  n4
                (modulo n1 n2)          -->  n4

remainder and modulo differ on negative arguments as do the 
Common Lisp rem and mod procedures -- the remainder always has 
the sign of the dividend, the modulo always has the sign of the 
divisor: 

                (modulo 13 4)           -->  1
                (remainder 13 4)        -->  1

                (modulo -13 4)          -->  3
                (remainder -13 4)       -->  -1

                (modulo 13 -4)          -->  -3
                (remainder 13 -4)       -->  1

                (modulo -13 -4)         -->  -1
                (remainder -13 -4)      -->  -1


(gcd n1 ...)                                            procedure
(lcm n1 ...)                                            procedure

These procedures return the greatest common divisor or least 
common multiple of their arguments.  The arguments to lcm should 
be nonzero.  The result is always non-negative.  

                (gcd 32 -36)            -->  4
                (gcd)                   -->  0
                (lcm 32 -36)            -->  288
                (lcm)                   -->  1


(floor x)                                               procedure
(ceiling x)                                             procedure
(truncate x)                                            procedure
(round x)                                               procedure
(rationalize x y)                                       procedure
(rationalize x)                                         procedure

These procedures create integers and rationals.  Their results 
are not EXACT -- in fact, their results are clearly INEXACT, 
though they can be made EXACT with an explicit exactness 
coercion.  

floor returns the largest integer not larger than x.  ceiling 
returns the smallest integer not smaller than x.  truncate 
returns the integer of maximal absolute value not larger than x.  
round returns the closest integer to x, rounding to even when x 
is halfway between two integers.  With two arguments, 
rationalize produces the best rational approximation to x within 
the tolerance specified by y.  With one argument, rationalize 
produces the best rational approximation to x, preserving all of 
the precision in its representation.  


(exp z)                                                 procedure
(log z)                                                 procedure
(expt z1 z2)                                            procedure
(sqrt z)                                                procedure
(sin z)                                                 procedure
(cos z)                                                 procedure
(tan z)                                                 procedure
(asin z)                                                procedure
(acos z)                                                procedure
(atan z1 z2)                                            procedure           

These procedures are part of every implementation that supports 
real numbers.  Their meanings conform with the Common Lisp 
standard.  (Be careful of the branch cuts if complex numbers are 
allowed.) 


(make-rectangular x1 x2)                                procedure
(make-polar x3 x4)                                      procedure
(real-part z)                                           procedure
(imag-part z)                                           procedure
(magnitude z)                                           procedure
(angle z)                                               procedure

These procedures are part of every implementation that supports 
complex numbers.  Suppose x1, x2, x3, and x4 are real numbers 
and z is a complex number such that 

                 z = x1 + x2 i = x3 * e ↑ (x4 i)

Then make-rectangular and make-polar return z, real-part returns 
x1, imag-part returns x2, magnitude returns x3, and angle 
returns x4.  


(exact->inexact z)                                      procedure
(inexact->exact z)                                      procedure

exact->inexact returns an inexact representation of z, which is 
a pretty harmless thing to do.  inexact->exact returns an exact 
representation of z; be sure you know what you are doing here! 
!II.7.  Numbers (part 2) 


Numerical Input and Output.  

Scheme allows all of the traditional ways of expressing 
numerical constants, though any particular implementation may 
support only some of them.  These expressions are intended to be 
purely notational; any kind of number may be expressed in any 
form that the user deems convenient.  Of course, expressing 1/7 
as a limited-precision decimal fraction will not exactly express 
the number, but this approximate expression may be just what the 
user wants to see.  

The expressions of numerical constants can be specified using 
formats.  The system provides a procedure, number->string, which 
takes a number and a format and which produces a string which is 
the printed expression of the given number in the given format.  



(number->string number format)                          procedure

This procedure will mostly be used by sophisticated users and in 
system programs.  In general, a naive user will need to know 
nothing about the formats because the system printer will have 
reasonable default formats for all types of NUMBERs.  The system 
reader will construct reasonable default numerical types for 
numbers expressed in each of the formats it recognizes.  If a 
user needs control of the coercion from strings to numbers he 
will use string->number, which takes a string, an exactness, and 
a radix and which produces a number of the maximally precise 
applicable type expressed by the given string.  


(string->number string exactness radix)                 procedure

The exactness is a symbol, either E (for EXACT) or I (for 
INEXACT).  The radix is also a symbol: B for binary, O for 
octal, D for decimal, and X for hexadecimal.  Returns a number 
parsed from the string.  


Formats may have parameters.  For example, the (SCI 5 2) format 
specifies that a number is to be expressed in Fortran scientific 
format with 5 significant places and two places after the radix 
point.  

The following are all numerical constant expressions.  The 
comment shows the format that was used to produce the 
expression: 

    123  +123  -123                    ; (INT)
    12345678901234567890123456789      ; A big one!
    355/113  -355/113  +355/113        ; (RAT)
    +123.45  -123.45                   ; (FIX 2)
    3.14159265358979                   ; (FIX 14)
    3.14159265358979                   ; (FLO 15)
    123.450                            ; (FLO 6)
    -123.45E-1                         ; (SCI 5 2)
    123E3  123E-3  -123E-3             ; (SCI 3 0)
    -1+2i                              ; (RECT (INT) (INT))
    1.2@1.570796                       ; (POLAR (FIX 1) (FLO 7))

A numerical constant may be specified with an explicit radix by 
a prefix.  The prefixes are: #B (binary), #O (octal), #D 
(decimal), #X (hex).  A format may specify that a number be 
expressed in a particular radix.  The radix prefix may be 
suppressed.  For example, one may express a complex number in 
polar form with the magnitude in octal and the angle in decimal 
as follows: 

    #o1.2@#d1.570796327  ; (POLAR (FLO 2 (RADIX O)) (FLO (RADIX D)))
    #o1.2@1.570796327    ; (POLAR (FLO 2 (RADIX O)) (FLO (RADIX D S))

A numerical constant may be specified to be either EXACT or 
INEXACT by a prefix.  The prefixes are: #I (inexact), #E 
(exact).  An exactness prefix may appear before or after any 
radix prefix that is used.  A format may specify that a number 
be expressed with an explicit exactness prefix, or it may force 
the exactness to be suppressed.  For example, the following are 
ways to output an inexact value for pi: 

    #I355/113           ; (RAT (EXACTNESS))
    355/113             ; (RAT (EXACTNESS S))
    #I3.1416            ; (FIX 4 (EXACTNESS))

An attempt to produce more digits than are available in the 
internal machine representation of a number will be marked with 
a "#" filling the extra digits.  This is not a statement that 
the implementation knows or keeps track of the significance of a 
number, just that the machine will flag attempts to produce 20 
digits of a number which has only 15 digits of machine 
representation: 

    3.14158265358979#####       ; (FLO 20 (EXACTNESS S))

In systems with both single and double precision FLONUMs one may 
want to specify which size we want to use to internally 
represent a constant.  For example, we may want a constant that 
is pi rounded to the single precision length, or we might want a 
long number which has the value 6/10.  In either case, we are 
specifying an explicit way to represent an INEXACT number.  For 
this purpose, we allow one to express a number with a prefix 
which indicates short or long FLONUM representation: 

    #S3.14159265358979          ; Round to short -- 3.141593
    #L.6                        ; Extend to long -- .600000000000000



Details of formats.  

The format of a number is notated as a list beginning with a 
format descriptor, such as SCI.  Following the descriptor are 
parameters used by that descriptor, such as the number of 
significant digits to be used.  Parameters which are omitted are 
defaulted.  Next, one may specify modifiers, such as RADIX or 
EXACTNESS, which themselves may be parameterized.  The format 
descriptors are: 

 (INT)
   Express as an integer.  The radix point is implicit.  If there are
   not enough significant places, as in trying to express 6.0238E23
   (internally represented as a 7 digit FLONUM) as an integer we would
   get "6023800################".

 (RAT n)
   Express as a rational fraction.  n specifies the largest
   denominator to be used in constructing a rational approximation to
   the number being expressed.  If n is omitted it defaults to
   infinity. 

 (FIX n)
   Express with a fixed radix point.  n specifies the number of
   places to the right of the radix point.  n defaults to the size of a
   single-precision FLONUM.  If there are not enough significant
   places, as in trying to express 6.0238E23 (internally represented
   as a 7 digit FLONUM) as a (FIX 2) we would get
   "6023800################.##".

 (FLO n) 
   Express with a floating radix point.  n specifies the total number
   of places to be displayed.  n defaults to the size of a single-
   precision FLONUM.  If the number is out of range, it is converted
   to (SCI).  (FLO H) allows the system to heuristically express a FLO
   for human consumption (as in the MacLisp printer).

 (SCI n m)
   Express in exponential notation.  n specifies the total number of
   places to be displayed.  n defaults to the size of a single-
   precision FLONUM.  m specifies the number of places to the right of
   the radix point.  m defaults to n-1.  (SCI H) does heuristic
   expression. 

 (RECT r i)
   Express as a rectangular form complex number.  r and i are formats
   for the real and imaginary parts respectively.  They default to

∂19-Mar-85  0515	@MIT-MC:forwarder@CSNET-SH.ARPA 	Message a011267 LONG message - part 3
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  05:15:11 PST
Received: from CSNET-SH by MIT-MC.ARPA; 19 MAR 85 08:07:47 EST
To: scheme@MIT-MC.ARPA
Subject: Message a011267 LONG message - part 3
Reply-to: cic@CSNET-SH.ARPA
Date: 19 Mar 85 07:53:34 EST (Tue)
From: "Charlotte D. Mooers" <postmaster@CSNET-SH.ARPA>


   (HEUR).

 (POLAR m a)
   Express as a polar form complex number.  m and a are formats for
   the magnitude and angle respectively.  m and a default to (HEUR).

 (HEUR)
   Express heuristically, as in the MacLisp printer (see Steele),
   using the minimum number of digits required to get an expression
   which when coerced back to a number produces the original machine
   representation.  EXACT numbers are expressed as (INT) or (RAT).
   INEXACT numbers are expressed as (FLO H) or (SCI H) depending on
   their range.  Complex numbers are expressed in (RECT).  This is the
   normal default of the system printer.


The following modifiers may be added to a numerical format 
specification: 

 (EXACTNESS s)
   This controls the expression of the exactness label of a number.  s
   indicates whether the exactness is to be E (expressed) or S
   (suppressed).  s defaults to E.  If no exactness modifier is
   specified for a format the exactness is by default not expressed.

 (RADIX r s)
   This forces a number to be expressed in the radix r.  r may be B
   (binary), O (octal), D (decimal), or X (hex).  s indicates whether
   the radix label is to be E (expressed) or S (suppressed).  s
   defaults to E.  If no radix modifier is specified the default is 
   decimal and the label is suppressed.


! II.8.  Strings


Strings are written as sequences of characters enclosed within 
doublequotes (").  A doublequote can be written inside a string 
only by escaping it with a backslash (\), as in 

      "The word \"Recursion\" has many different meanings."

A backslash can be written inside a string only by escaping it 
with another backslash.  Scheme does not specify the effect of a 
backslash within a string that is not followed by either a 
doublequote or another backslash.  

A string may continue from one line to the next, but this is 
usually a bad idea because the exact effect varies from one 
computer system to another.  

Several of the string procedures involve characters or lists of 
characters.  Characters are written using the #\ notation of 
Common Lisp.  For example: 

        #a           ; lower case letter
        #A           ; upper case letter
        #(           ; the left parenthesis as a character
        #            ; the space character
        #space       ; the preferred way to notate a space character
        #newline     ; the newline character

The #\ notation is not an essential part of Scheme, however.  
Even implementations that support the #\ notation for input do 
not have to support it for output, and there is no requirement 
that the data type of characters be disjoint from data types 
such as integers or strings.  

This section defines no destructive operations on strings, but a 
much larger collection of string operations including 
destructive operations has been proposed by Chris Hanson and is 
under consideration.  


(string? obj)                                 essential procedure

Returns #!true if obj is a string, otherwise returns #!false.  


(string-equal? string1 string2)               essential procedure

Returns #!true if string1 and string2 are strings of the same 
length and have the same characters in the same positions.  


(string-less? string1 string2)                essential procedure

Returns #!true if string1 is lexicographically less than 
string2.  The ordering defined by string-less? varies from one 
computer system to another, but it is always an irreflexive 
total ordering on strings.  


(string-length string)                        essential procedure

Returns the number of characters in string.  


(string-ref string k)                         essential procedure

k must be a nonnegative integer less than the string-length of 
string.  Returns character k of string using zero-origin 
addressing.  

        (string-ref "abcde" 2)          -->  #c 


(string-append string1 string2)               essential procedure
(string-append string ...)                              procedure

Returns a string whose characters form the catenation of the 
given strings.  


(string->list string)                         essential procedure

Returns a list of the characters that make up string.  See 
list->string.  


(list->string char-list)                      essential procedure

char-list must be a proper list of characters.  Returns a string 
formed from the characters in char-list.  list->string and 
string->list are inverses so far as equal? is concerned.  
!II.9.  Vectors 


Vectors are heterogenous mutable structures whose elements are 
indexed by integers.  The first element in a vector is indexed 
by zero, and the last element is indexed by one less than the 
length of the vector.  A vector of length 3 containing the 
number 0 in element 0, the list (2 2 2 2) in element 1, and the 
string "Anna" in element 2 can be written as 

                      #(0 (2 2 2 2) "Anna")

Vectors are created by the constructor procedure make-vector.  
The elements are accessed and assigned by the procedures 
vector-ref and vector-set!.  


(vector? obj)                                 essential procedure

Returns #!true if obj is a vector, otherwise returns #!false.  


(make-vector size)                            essential procedure
(make-vector size fill)                                 procedure

Returns a newly allocated vector of size elements.  If a second 
argument is given, then each element is initialized to fill.  
Otherwise the initial contents of each element is unspecified.  


(vector obj ...)                              essential procedure

Returns a newly allocated vector whose elements contain the 
given arguments.  Analogous to list.  

        (vector 'a 'b 'c)               -->  #(a b c)


(vector-length vec)                           essential procedure

Returns the number of elements in the vector vec.  


(vector-ref vec k)                            essential procedure

Returns the contents of element k of the vector vec.  k must be 
a nonnegative integer less than the vector-length of vec.  

  (vector-ref '#(1 1 2 3 5 8 13 21) 5)  -->  8


(vector-set! vec k obj)                       essential procedure

Stores obj in element k of the vector vec.  k must be a 
nonnegative integer less than the vector-length of vec.  The 
value returned by vector-set! is not specified.  

    (define vec '#(0 (2 2 2 2) "Anna")) -->  vec
    (vector-set! vec 1 '("Sue" "Sue"))  -->  unspecified
    vec                                 -->  #(0
                                               ("Sue" "Sue")
                                               "Anna")


(vector->list vec)                            essential procedure

Returns a list of the objects contained in the elements of vec.  
See list->vector.  

    (vector->list '#(dah dah didah))    -->  (dah dah didah)


(list->vector elts)                           essential procedure

Returns a newly created vector whose elements are initialized to 
the elements of the proper list elts.  

        (list->vector '(dididit dah))   -->  #(dididit dah)


(vector-fill! vec fill)                                 procedure

Stores fill in every element of the vector vec.  The value 
returned by vector-fill! is not specified.  
!II.10.  The object table 


(object-hash obj)                                       procedure
(object-unhash n)                                       procedure

object-hash associates an integer with obj in a global table and 
returns obj.  object-hash guarantees that distinct objects (in 
the sense of eq?) are associated with distinct integers.  
object-unhash takes an integer and returns the object associated 
with that integer if there is one, returning false otherwise.  

Rationale: object-hash and object-unhash can be implemented 
using association lists and the assq procedure, but the intent 
is that they be efficient hash functions for general objects.  
!II.11.  Procedures 


Procedures are created when lambda expressions are evaluated.  
Procedures do not have a standard printed representation because 
recursively defined procedures are conceptually infinite and may 
be implementationally circular.  

The most common thing to do with a procedure is to call it with 
zero or more arguments.  A Scheme procedure may also be stored 
in data structures or passed as an argument to procedures such 
as those described below.  


(apply proc args)                             essential procedure
(apply proc arg1 ... args)                              procedure

proc must be a procedure and args must be a proper list of 
arguments.  The first (essential) form calls proc with the 
elements of args as the actual arguments.  The second form is a 
generalization of the first that calls proc with the elements of 
(append (list arg1 ...) args) as the actual arguments.  

    (apply + (list 3 4))                -->  7

    (define compose
      (lambda (f g)
        (lambda args
          (f (apply g args)))))         -->  compose

    ((compose 1+ *) 3 4)                -->  13


(mapcar f plist)                              essential procedure
(mapcar f plist1 plist2 ...)                            procedure

f must be a procedure of one argument and the plists must be 
proper lists.  If more than one plist is given, then the plists 
should all be the same length.  Applies f element-wise to the 
elements of the plists and returns a list of the results.  The 
order in which f is applied to the elements of the plists is not 
specified.  

    (mapcar cadr '((a b) (d e) (g h)))  -->  (b e h)

    (mapcar (lambda (n) (expt n n))
            '(1 2 3 4 5))               -->  (1 4 27 256 3125)

    (mapcar + '(1 2 3) '(4 5 6))        -->  (5 7 9)

    (define count 0)                    -->  unspecified
    (mapcar (lambda (ignored)
              (set! count (1+ count))
              count)
            '(a b c))                   -->  unspecified

The mapcar procedure often goes by the name of map in other 
advanced programming languages.  


(mapc f plist)                                essential procedure
(mapc f plist1 plist2 ...)                              procedure

The arguments to mapc are like the arguments to mapcar, but mapc 
calls f for its side effects rather than for its values.  Unlike 
mapcar, mapc is guaranteed to call f on the elements of the 
plists in order from the first element to the last, and the 
value returned by mapc is not specified.  

    (define v (make-vector 5))          -->  v

    (mapc (lambda (i)
            (vector-set! v i (* i i)))
          '(0 1 2 3 4))                 -->  unspecified

    v                                   -->  #(0 1 4 9 16)

The name of mapc is traditional and cannot otherwise be 
defended.  


(call-with-current-continuation f)                      procedure

The classic use of call-with-current-continuation is for 
structured, non-local exits from loops or procedure bodies, but 
in fact call-with-current-continuation is extremely useful for 
implementing a wide variety of advanced control structures.  

Whenever a Scheme expression is evaluated there is a 
continuation wanting the result of the expression.  The 
continuation represents an entire future for the computation.  
If the expression is evaluated at top level, for example, then 
the continuation will take the result, print it on the screen, 
prompt for the next input, evaluate it, and so on forever.  Most 
of the time the continuation includes actions specified by user 
code, as in a continuation that will take the result, multiply 
it by the value stored in a local variable, add seven, and give 
the answer to the top level continuation to be printed.  
Normally these ubiquitous continuations are hidden behind the 
scenes and programmers don't think much about them.  On rare 
occasions, however, when programmers need to do something fancy, 
then they may need to deal with continuations explicitly.  
call-with-current-continuation allows Scheme programmers to 
create a procedure that acts just like the current continuation.  


f must be a procedure of one argument.  
call-with-current-continuation packages up the current 
continuation as an "escape procedure" and passes it as an 
argument to f.  The escape procedure is an ordinary Scheme 
procedure of one argument that, if it is later passed a value, 
will ignore whatever continuation is in effect at that later 
time and will give the value instead to the continuation that 
was in effect when the escape procedure was created.  

The escape procedure created by call-with-current-continuation 
has unlimited extent just like any other procedure in Scheme.  
It may be stored in variables or data structures and may be 
called as many times as desired.  

The following examples show only the most common uses of 
call-with-current-continuation.  If all real programs were as 
simple as these examples, there would be no need for a procedure 
with the power of call-with-current-continuation.  

    (call-with-current-continuation
      (lambda (exit)
        (mapc (lambda (x)
                (if (negative? x)
                    (exit x)))
              '(54 0 37 -3 245 19))
        #!true))                        -->  -3

    (define list-length
      (lambda (obj)
        (call-with-current-continuation
          (lambda (return)
            ((rec loop (lambda (obj)
                         (cond ((null? obj) 0)
                               ((pair? obj)
                                (1+ (loop (cdr obj))))
                               (else (return #!false)))))
             obj)))))
                                        -->  list-length

    (list-length '(1 2 3 4))            -->  4

    (list-length '(a b . c))            -->  #!false


Rationale: Most serious programming languages incorporate one or 
more special purpose escape constructs with names like exit, 
return, or even goto.  In 1965, however, Peter Landin invented a 
general purpose escape operator called the J-operator.  John 
Reynolds described a simpler but equally powerful construct in 
1972.  The catch special form described by Sussman and Steele in 
the 1975 report on Scheme is exactly the same as Reynolds's 
construct, though its name came from a less general construct in 
MacLisp.  The fact that the full power of Scheme's catch could 
be obtained using a procedure rather than a special form was 
noticed in 1982 by the implementors of Scheme 311, and the name 
call-with-current-continuation was coined later that year.  Some 
people think the name is good because its length discourages 
programmers from using the procedure casually; others have taken 
to calling the procedure call/cc.  
!II.12.  Ports 


Ports represent input and output devices.  To Scheme, an input 
device is a Scheme object that can deliver characters upon 
command, while an output device is a Scheme object that can 
accept characters.  


(call-with-input-file string proc)            essential procedure
(call-with-output-file string proc)           essential procedure

proc is a procedure of one argument, and string is a string 
naming a file.  For call-with-input-file, the file must already 
exist; for call-with-output-file, the effect is unspecified if 
the file already exists.  Calls proc with one argument: the port 
obtained by opening the named file for input or output.  If the 
file cannot be opened, an error is signalled.  If the procedure 
returns, then the port is closed automatically and the value 
yielded by the procedure is returned.  If the current 
continuation ever changes in such a way as to make it doubtful 
that the procedure will return, the port may be closed 
automatically, but the exact interaction with escape procedures 
is unspecified.  

Rationale: Whether or not the port is closed when the procedure 
does not return is mainly a performance issue, of greatest 
importance when there is a small limit on the number of files 
that can be open at once.  The extreme generality of Scheme's 
escape procedures makes it impossible to know for certain 
whether a procedure will return, and procedures can in fact 
return more than once.  


(input-port? obj)                             essential procedure
(output-port? obj)                            essential procedure

Returns #!true if obj is an input port or output port 
(respectively), otherwise returns #!false.  


(current-input-port)                          essential procedure
(current-output-port)                         essential procedure

Returns the current default input or output port.  


(with-input-from-file string thunk)                     procedure
(with-output-to-file string thunk)                      procedure

thunk is a procedure of no arguments, and string is a string 
naming a file.  For with-input-from-file, the file must already 
exist; for with-output-to-file, the effect is unspecified if the 
file already exists.  The file is opened for input or output, an 
input or output port connected to it is made the default value 
returned by current-input-port or current-output-port, and the 
thunk is called with no arguments.  When the thunk returns, the 
port is closed and the previous default is restored.  
with-input-from-file and with-output-to-file return the value 
yielded by thunk.  Furthermore these procedures will attempt to 
close the default port and restore the previous default whenever 
the current continuation changes in such a way as to make it 
doubtful that the thunk will ever return.  See 
call-with-input-file and call-with-output-file.  


(open-input-file filename)                              procedure

Takes a string naming an existing file and returns an input port 
capable of delivering characters from the file.  If the file 
cannot be opened, an error is signalled.  


(open-output-file filename)                             procedure

Takes a string naming an output file to be created and returns 
an output port capable of writing characters to a new file by 
that name.  If the file cannot be opened, an error is signalled.  
If a file with the given name already exists, the effect is 
unspecified.  


(close-input-port port)                                 procedure
(close-output-port port)                                procedure

Closes the file associated with port, rendering the port 
incapable of delivering or writing characters.  The value 
returned is not specified.  
!II.13.  Input 


The read procedure converts written representations of Scheme 
objects into the objects themselves.  The written 
representations for Scheme objects are described in the sections 
devoted to the operations on those objects, and the grubby 
details of lexical syntax are described in an appendix.  


(eof? obj)                                    essential procedure

Returns true iff obj is an end of file object.  The precise set 
of end of file objects will vary among implementations, but in 
any case no end of file objects will ever be a character or an 
object that can be read in using read.  


(read)                                        essential procedure
(read port)                                   essential procedure

Returns the next object parsable from the given input port, 
updating port to point to the first character past the end of 
the written representation of the object.  If an end of file is 
encountered in the input before any characters are found that 
can begin an object, then an end of file object is returned.  If 
an end of file is encountered after the beginning of an object's 
written representation, but the written representation is 
incomplete and therefore not parsable, an error is signalled.  
The port argument may be omitted, in which case it defaults to 
the value returned by current-input-port.  

Rationale: This corresponds to Common Lisp's 
read-preserving-whitespace, but for simplicity it is never an 
error to encounter end of file except in the middle of an 
object.  


(read-char)                                   essential procedure
(read-char port)                              essential procedure

Reads the next character available from the input port, updating 
the port to point to the following character.  If no more 
characters are available, an end of file object is returned.  
port may be omitted, in which case it defaults to the value 
returned by current-input-port.  


(listen?)                                               procedure
(listen? port)                                          procedure

Returns true if a character is ready on the input port so that a 
read-char operation will not hang, and returns false otherwise.  
If the port is at end of file then the value returned by listen? 
is unspecified.  port may be omitted, in which case it defaults 
to the value returned by current-input-port.  


(load filename)                               essential procedure

filename should be a string naming an existing file containing 
Scheme source code.  The load procedure reads expressions from 
the file and evaluates them sequentially as though they had been 
typed interactively.  It is not specified whether the results of 
the expressions are printed, however, nor is it specified 
whether the load procedure affects the values returned by 
current-input-stream and current-output-stream during the 
loading process.  load returns an unspecified value.  

Rationale: For portability load must operate on source files.  
Its operation on other kinds of files necessarily varies among 
implementations.  
!II.14.  Output 


(write obj)                                   essential procedure
(write obj port)                              essential procedure

Writes a representation of obj to the given port.  Strings that 
appear in the written representation are enclosed in 
doublequotes, and within those strings backslash and doublequote 
characters are escaped by backslashes.  write returns an 
unspecified value.  The port argument may be omitted, in which 
case it defaults to the value returned by current-output-stream.  
See display.  


(display obj)                                 essential procedure
(display obj port)                            essential procedure

Writes a representation of obj to the given port.  Strings that 
appear in the written representation are not enclosed in 
doublequotes, and no characters are escaped within those 
strings.  display returns an unspecified value.  The port 
argument may be omitted, in which case it defaults to the value 
returned by current-output-stream.  See write.  

Rationale: Like Common Lisp's prin1 and princ, write is for 
producing machine-readable output and display is for producing 
human-readable output.  Implementations that allow 
"slashification" within symbols will probably want write but not 
display to slashify funny characters in symbols.  


(newline)                                     essential procedure
(newline port)                                essential procedure

Writes an end of line to port.  Exactly how this is done differs 
from one operating system to another.  Returns an unspecified 
value.  The port argument may be omitted, in which case it 
defaults to the value returned by current-output-port.  


(write-char char)                             essential procedure
(write-char char port)                        essential procedure

Writes the character char (not a written representation of the 
character) to the given port and returns an unspecified value.  
The port argument may be omitted, in which case it defaults to 
the value returned by current-output-port.  


(transcript-on filename)                                procedure
(transcript-off)                                        procedure

filename must be a string naming an output file to be created.  
The effect of transcript-on is to open the named file for 
output, and to cause a transcript of subsequent interaction 
between the user and the Scheme system to be written to the 
file.  The transcript is ended by a call to transcript-off, 
which closes the transcript file.  Only one transcript may be in 
progress at any time, though some implementations may relax this 
restriction.  The values returned by these procedures are 
unspecified.  

Rationale: These procedures are redundant in some systems, but 
systems that need them should provide them.  
!References 




Harold Abelson and Gerald Jay Sussman with Julie Sussman, 
Structure and Interpretation of Computer Programs, MIT Press, 
1985.  

William Clinger, "The Scheme 311 compiler: an exercise in 
denotational semantics", Conference Record of the 1984 ACM 
Symposium on Lisp and Functional Programming, August 1984, pages 
356-364.  

Carol Fessenden, William Clinger, Daniel P Friedman, and 
Christopher Haynes, "Scheme 311 version 4 reference manual", 
Indiana University Computer Science Technical Report 137, 
February 1983.  

D Friedman, C Haynes, E Kohlbecker, and M Wand, "Scheme 84 
interim reference manual", Indiana University Computer Science 
Technical Report 153, January 1985.  

Christopher T Haynes, Daniel P Friedman, and Mitchell Wand, 
"Continuations and coroutines", Conference Record of the 1984 
ACM Symposium on Lisp and Functional Programming, August 1984, 
pages 293-298.  

Peter Landin, "A correspondence between Algol 60 and Church's 
lambda notation: Part I", Communications of the ACM 8, 2, 
February 1965, pages 89-101.  

MIT Scheme Manual, Seventh Edition, September 1984.  

Peter Naur et al, "Revised report on the algorithmic language 
Algol 60", Communications of the ACM 6, January 1963, pages 
1-17.  

Kent M Pitman, The Revised MacLisp Manual, MIT Artificial 
Intelligence Laboratory Technical Report 295, 21 May 1983 
(Saturday Evening Edition).  

Jonathan A Rees, Norman I Adams, James R Meehan, "The T manual", 
Fourth Edition, 10 January 1984.  

John Reynolds, "Definitional interpreters for higher order 
programming languages", ACM Conference Proceedings, 1972, pages 
717-740.  

Guy Lewis Steele Jr and Gerald Jay Sussman, "The revised report 
on Scheme, a dialect of Lisp", MIT Artificial Intelligence 
Laboratory Memo 452, January 1978.  

Guy L Steele, Rabbit: a compiler for Scheme, MIT Artificial 
Intelligence Laboratory Technical Report 474, May 1978.  

Guy L Steele, "An overview of Common Lisp", Conference Record of 
the 1982 ACM Symposium on Lisp and Functional Programming, 
August 1982, pages 98-107.  

Guy Lewis Steele Jr, Common Lisp: the Language, Digital Press, 
1984.  

Gerald Jay Sussman and Guy Lewis Steele Jr, "Scheme: an 
interpreter for extended lambda calculus", MIT Artificial 
Intelligence Laboratory Memo 349, December 1975.  

Gerald Jay Sussman, Jack Holloway, Guy L Steele, and Alan Bell, 
"Scheme-79 -- Lisp on a chip", IEEE Computer 14, 7, July 1981, 
pages 10-21.  


∂19-Mar-85  1044	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	Keyboard inputs    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  10:44:39 PST
Received: from csnet-relay by MIT-MC.ARPA; 19 MAR 85 13:43:27 EST
Received: from indiana by csnet-relay.csnet id a008437; 19 Mar 85 13:42 EST
Date: Tue, 19 Mar 85 10:55:58 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA03087; Tue, 19 Mar 85 10:55:58 est
To: scheme@mit-mc.ARPA
Subject: Keyboard inputs

>        On interactive streams users may have the possibility of
>erasing typed characters.  What happens if listen? returns true and
>then the user erases the character?  The program which invoked listen?
>will probably attempt to read a character thinking that it will not
>hang but it will.  We had this bug and went to a fair amount of hair
>to get it fixed.

This problem doesn't arise if the rubout handler is implemented
using READ-CHAR.  The system should be designed this way if you
expect to implement an Emacs-like editor in Scheme.

If the rubout handler is at a lower level than READ-CHAR, then
the system is probably set up so that the user first edits her
input using rubouts and whatever other facilities are available
(cut and paste using a mouse, Emacs, whatever).  Let's say that
this input is liquid.  When the user is satisfied with her input
she does something to signal that the input should be sent to
Scheme, perhaps by typing the "Execute" key (on the HP 9836) or
the "Enter" key (on the Macintosh).  At that moment the input
should be frozen so that it cannot be edited further.  At any
given time the input buffer for READ-CHAR may contain older
characters that are frozen as well as newer characters that are
liquid.  READ-CHAR should return only frozen characters, and
should hang if there are none. The LISTEN? procedure (or whatever
we wind up calling it) should therefore return true only if there
are frozen characters in the buffer.

It is possible to design a system that can switch back and forth
between the first way and the second way. (Unix calls these raw
mode and cooked mode.)



>       We have not talked at all about keyboard interrupts.  It
>seems to me that any reasonable implementation should provide a
>way for the user to (at least) abort an infinite loop.  It would
>be nice if we had a simple standard mechanism for doing this, but
>implementations would be free to have more keyborad interrupts
>(we currently have 5 by default).  I propose that we choose some
>control character (↑G, for example) which on all implementations
>and unless inhibited (an editor may want to do this) will
>interrupt Scheme and make it return to the top-level
>read-eval-print loop.

Yes, any reasonable implementation must have keyboard interrupts,
but we shouldn't standardize on the characters.  Consider Scheme
312, which runs under four very different operating systems.
Under CP/M-68k, control-G is fine as the interrupt character, and
an operating system convention leads users to expect that
control-C will leave Scheme for good (it does).  Under Un*x,
however, users expect SIGINT to be the interrupt character and
SIGQUIT to be the abort character; usually these are control-C
and control-\, respectively.  Under HP Pascal the HP 9836
"Execute" key is rigged to send a control-C; it doesn't make
sense for "Execute" to interrupt or abort.  The Macintosh doesn't
have a control key (the command (cloverleaf) key is something
completely different); pull-down menus are probably more
appropriate.  In short, no matter what conventions we could
choose, they would be wrong for some machines.


∂19-Mar-85  1445	@MIT-MC:JINX@MIT-OZ 	Keyboard inputs    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  14:45:37 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 19 MAR 85  17:44:34 EST
Date: 19 Mar 1985  17:44 EST (Tue)
Message-ID: <JINX.12096359061.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Will Clinger <willc%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: Keyboard inputs
In-reply-to: Msg of 19 Mar 1985  10:55-EST from Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

	I think you don't understand the problem with listen?

	The system need not have a rubout handler written in Scheme to
have an Emacs-like editor.  MIT-Scheme has a rubout handler written in
Pascal (almost all IO is written in Pascal), and Edwin (Chris Hanson's
editor) works perfectly fine, since it bypasses buffered IO.

	We have two kinds of terminal read-char: One is used by the
reader, and is buffered (no characters are given to Scheme until some
key (Execute on HP9836, Newline on UNIX) is typed).  The other is
immediate (it returns as soon as a character is typed, without waiting
for any special character).  The former is much more efficient under
some operating systems, and eliminates the need for a complicated
rubout handler since the reader never needs to back out (according to
GJS, 1/4 of all the code of MacLisp at some point was the rubout
handler).  Having an Emacs-like front-end is not incompatible with
this, since the front-end need not give any characters to Scheme until
no further character-level processing is needed.

	It is inconvenient, however, to do all input in this mode (I'd
hate to have to type a newline after a single character command to a
debugger, for example).  This is why we have immediate read-char also,
which is the default.  Users can type asynchronously, and frequently
do so ahead of the system.  For consistency, the user should be able
to edit (especially rub-out) his typeahead until it is read.  Since
the system does not know whether the next read-char will be immediate
or not, it cannot lock the required characters unless it locks all,
clearly unpalatable.

	The problem with listen? arises, for example, from programs
which ask for confirmation or a simple choice but assume a default if
no input becomes available in some period of time.  Assume that the
user types a character, the program invokes listen? which returns
true, and the user then deletes the character before the program has
had a chance to invoke immediate read-char.  This is quite likely on a
timesharing system, where the user may delete while Scheme is not the
current process running.  Clearly the program will hang while it
should not (it was intended that it "time-out").  Clearly listen? is
wothless unless it applies to both liquid and frozen characters
(otherwise a terminator would have to be typed after the option,
ugh!).  The problem is trivially solved if listen? locks the
character.

	I believe that this problem can arise even if there is no
buffered io in a system.  On Lisp systems that I know (including
MacLisp and Lisp Machines), rubout-handling is built into read, not
into tyi, and therefore user programs that use tyi rather than read do
not (by default) allow users to rub-out their input.  If you allow
rub-out on read-char throughout the system (which is certainly
desirable), the problem potentially exists.

	Since adding this extra constraint to the definition of
listen? solves all these bugs and allows implementors of the
io system greater freedom, I think it should be added.

	On my previous message I advocated for eliminating listen? in
favor of non-hanging-read-char, but I drop this.  Chris Hanson has
pointed out that unless untyi were provided, this would be the cause
of pretty ugly code.

∂19-Mar-85  2228	@MIT-MC:CPH@MIT-OZ 	Revisions to String Proposal  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Mar 85  22:28:35 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 20 MAR 85  01:24:39 EST
Date: Wed, 20 Mar 1985  01:24 EST
Message-ID: <CPH.12096442797.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Scheme@MIT-MC
Subject: Revisions to String Proposal

I have revised the earlier proposal I submitted for String operations.
The revision was somewhat of a hatchet job, but I think that the
important functionality remains.

What follows is some notes referring to the earlier proposal.  After
that I have written a small bit of commentary about mutation of
strings.
!
----------------------------------------------------------------------

			      Characters

The basic operations on characters are the following; they should be
essential. 

  (CHAR? <object>)
    True iff <object> is a character.

  (CHAR->INTEGER <char>)
  (INTEGER->CHAR <integer>)
    Maps to coerce characters to integers and vice versa.  If two
    characters have a certain relationship in the character ordering,
    then the corresponding integers must have the same relationship in
    the integer ordering.  (If I recall right, this means these maps
    are order isomorphisms between characters and integers.)

I would like to propose that the following be essential.  These are
the case sensitive order predicates for characters; they define the
character ordering.  I think that the Common Lisp restrictions as to
the ordering should be adopted.

The names have been changed to conform with Common Lisp, after Don
Oxley pointed out that CHAR-EQUAL? was case sensitive, and in CL
CHAR-EQUAL was the case insensitive version.  I hope that this will
clear things up a bit.

Each of the following accepts two character objects, and compares them
in the obvious way.  Optionally, they may take more arguments, as do
the corresponding numeric predicates.

    CHAR=?  CHAR<?  CHAR<=?  CHAR>?  CHAR>=?

The following should be optional; they are the case insensitive
versions of the above.

    CHAR-CI=?  CHAR-CI<?  CHAR-CI<=?  CHAR-CI>?  CHAR-CI>=?

These character class predicates should be optional, with the meaning
described in the Common Lisp manual.  They each take one argument,
which must be a character.

    CHAR-UPPER-CASE?
    CHAR-LOWER-CASE?
    CHAR-ALPHABETIC?
    CHAR-NUMERIC?
    CHAR-ALPHANUMERIC?
    CHAR-WHITESPACE?
    CHAR-GRAPHIC?

The following should be optional; each takes a character object and
returns another character object.  They perform case conversion if the
argument is lower or upper case, respectively.

    CHAR-UPCASE
    CHAR-DOWNCASE
!
----------------------------------------------------------------------

			       Strings

I think that the following should be essential, as described in my
earlier proposal:

    STRING?  MAKE-STRING  STRING-LENGTH  STRING-REF  STRING->LIST
    LIST->STRING  SUBSTRING  STRING-APPEND  STRING-NULL?

Similarly to the transformation for characters, the following should
be essential for two arguments, and optionally should take more.

    STRING=?  STRING<?  STRING<=?  STRING>?  STRING>=?

Again, these case insensitive versions are optional.

    STRING-CI=?  STRING-CI<?  STRING-CI<=?  STRING-CI>?  STRING-CI>=?

Next, these optional procedures provide a small set of operations for
mutable strings. 

    STRING-ALLOCATE  STRING-COPY  STRING-SET!  SUBSTRING-FILL!
    SUBSTRING-MOVE-RIGHT!  SUBSTRING-MOVE-LEFT!

The remaining operations, while useful, are probably not important
enough to standardize on.  As I have already demonstrated, all of them
can be implemented given the above operations.


Here is the corrected text for the -MOVE- operations:

(SUBSTRING-MOVE-RIGHT! STRING1 START1 END1 STRING2 START2)
(SUBSTRING-MOVE-LEFT! STRING1 START1 END1 STRING2 START2)

These operations destructively copy the substring <STRING1, START1,
END1> to the string STRING2 starting at the index START2.  It must be
the case that <STRING2, START2, (+ START2 (- END1 START1))> is a
substring; this latter substring is destructively modified to contain
the contents of the former substring.

The operations differ only when the two substrings overlap, i.e. when
STRING1 and STRING2 are EQ? and the index sets of the substrings are
not disjoint.  In this case, the operations are defined to copy the
elements of the first substring serially.  SUBSTRING-MOVE-RIGHT!
copies the first substring starting with the rightmost element,
proceeding to the left, while SUBSTRING-MOVE-LEFT! starts with the
leftmost element, proceeding to the right.  This has the effect that
the two operations can be used to shift groups of characters right or
left, respectively, within a given string.
!
----------------------------------------------------------------------

                               Mutation

I have tried to be careful about the issue of mutable strings.  None
of the operations which I have proposed as "essential" mutate strings.
I have provided a small set of operations, marked as "optional", which
DO mutate strings.  I believe that mutation of strings is basically
reasonable; although I understand that in some very important cases,
in particular the names of interned symbols, there should be some
guarantee that a string cannot be mutated.  I believe that this can be
solved by one of these simple methods:

1.  A string could have an internal bit which, when set, would prevent
mutation.

2.  There could be two types of strings.  In this case, it would be
reasonable to decide that the read/print syntax for mutable strings
need not be the same as for non-mutable strings.

Anyway, I have chosen to have all strings be mutable in the MIT
implementation, because that is the simplest choice providing the most
power.  To the best of my knowledge, no one has ever been screwed by
this decision, and it seems unlikely that anyone ever would.

∂20-Mar-85  1254	JAR@MIT-MC 	Ports and streams 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Mar 85  12:54:44 PST
Date: 20 March 1985 15:54-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  Ports and streams
To: SCHEME @ MIT-MC

I think that we generally agree that were it not for performance
reasons, we would have only streams (in the FP/A&S sense), and not
ports; am I correct?  E.g., a stream object would need to be consed for
each character read from or written to a file; this would mean frequent
GC's if a lot of file I/O was happening.  It's unfortunate that our
design is driven by considerations like this, but I guess that's how
things are.

So the I/O primitives in the essential dialect manipulate things called
ports, which are positions on streams of characters.  The two notions
are equivalent (ports could be defined if the only primitives were stream
primitives, and vice versa), so people who care about writing code
which does I/O in a pure style can still do so, by implementing
I/O streams in terms of I/O ports themselves.

So far so good.  This message is about terminology, not semantics.  I
think that "port" is a bad term.  The real-life usage of the term "port"
(door or harbor) doesn't seem to be a good fit with that of the word
"stream".  I guess the image that's intended is of a door, with the
program on one side and a stream of things on the other, and the things
coming into the program's awareness or control through the door.  Or
perhaps the stream flows through the door?  Streams flow under bridges,
maybe, or through channels (I don't like "channel" because it has
incompatible connotations in computer science), or into aqueducts or
over waterfalls, but through doors?  The other meaning of "port"
doesn't make sense: rivers or possibly streams might flow into harbors
or ports, but that's not what makes a port a port; a port is someplace
where ships dock, load, etc.  So "port" is a very strange word to use in
connection with streams.

A different metaphor is that a "port" is a sort of a cursor or a marker
which moves along a sequence (stream).  Well, what moves up and down a
sequence or stream?  Here are some transportation metaphors:

	line, screen	cursor
	conduit		vehicle
	rail		train
	road		car
	river		boat
	stream		raft

How about "raft"?  A raft might be an appropriate vehicle for a stream.
I guess this is pretty cutesy, but it's an idea.  One argument in favor
is that "raft" doesn't have connotations in computer science like many
other words (port, channel) do.  Also, the metaphor is obscure enough
that no one would need to know how silly it is; users could imagine that
RAFT is an acronym, or some technical term derived from some obscure
branch of mathematics or semantics, or whatever.  Sounds sort of like
"rack" or "rail," terms that certain language designers use without
embarrassment.  And it's short, a distinct advantage.

These two metaphors reflect the difference between a stream and a
streambed.  If you want to see everything which floats by on a stream,
it's sufficient to sit one place (e.g. on a bridge, or on a bank, or at
its outlet) and relax and enjoy the view.  "Stream" here is the stuff
that is flowing.  If, however, you want to see all the places that the
stream goes, you have to get on a raft or boat or just wade the entire
length of the thing from source to outlet.  This "stream" is a
geographical thing, something you'd find on a map.

Besides the fact that "port" is a mixed (or at least poor) metaphor, I
am opposed to the term because it reminds me of Franz Lisp.  I'd rather
not be reminded of Franz every time I use Scheme.

I know this is pretty random, but I just wanted to voice my unhappiness
and get people thinking about more appropriate terms.

Jonathan

∂20-Mar-85  1542	@MIT-MC:KMP@SCRC-STONY-BROOK 	Ports and streams   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Mar 85  15:42:09 PST
Received: from SCRC-STONY-BROOK by MIT-MC via Chaosnet; 20 MAR 85  18:36:30 EST
Received: from SCRC-RIO-DE-JANEIRO by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 200687; Wed 20-Mar-85 17:11:04-EST
Date: Wed, 20 Mar 85 17:11 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: Ports and streams
To: Scheme@MIT-MC.ARPA
cc: JAR@MIT-MC.ARPA
In-Reply-To: The message of 20 Mar 85 15:54-EST from Jonathan A Rees <JAR at MIT-MC>
Message-ID: <850320171127.2.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>

    Date: 20 March 1985 15:54-EST
    From: Jonathan A Rees <JAR @ MIT-MC>

    ... A different metaphor is that a "port" is a sort of a cursor or a 
    marker which moves along a sequence (stream).  Well, what moves up 
    and down a sequence or stream? How about "raft"?  ...

I also dislike "port" for much the same reasons as Jonathan presented.
I support the proposal for the new term "raft".

∂21-Mar-85  1448	@MIT-MC:linus!ramsdell@mitre-bedford 	MAPC and MAPCAR  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Mar 85  14:46:23 PST
Received: from mitre-bedford by MIT-MC.ARPA; 21 MAR 85 17:46:38 EST
Date: 21 Mar 1985 17:35:15-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA18613; Thu, 21 Mar 85 09:30:14 est
Date: Thu, 21 Mar 85 09:30:14 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503211430.AA18613@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: MAPC and MAPCAR

I mildly support the change from "port" to "raft", but
GREATLY support changes in other SCHEME names.  In particular,
I find the terms MAPC and MAPCAR offensive.  Why not use the
names WALK and MAP as is done in T?  

I like the idea of using english words as names.  Thus I prefer
LABELS to LETREC.  Given that some names will not be english,
at the very least, word parts can be separated with dash.

LETREC       => LET-REC
DEFREC       => DEF-REC
NEWLINE      => NEW-LINE

As you can guess, CAR and CDR are losers in my book.  How about:
CAR          => -<-
CDR          => ->-
CADR         => -<>-
CDAR         => -><-
CxxxR        => -xxx- with "A" substituted by "<" and "D" substituted by ">".

Bold and wonderful changes from traditional Lisps are being suggested by
the Scheme document, for example, dumping the confusion between the
empty list and logical false.  Now is no time to get stuck with 
traditional name.
John

∂21-Mar-85  1449	@MIT-MC:linus!ramsdell@mitre-bedford 	Re: DRAFT of the Revised Revised Report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Mar 85  14:48:42 PST
Received: from mitre-bedford by MIT-MC.ARPA; 21 MAR 85 17:47:31 EST
Date: 21 Mar 1985 17:35:34-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA21592; Thu, 21 Mar 85 13:35:25 est
Date: Thu, 21 Mar 85 13:35:25 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503211835.AA21592@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: Re: DRAFT of the Revised Revised Report

A few comments:

1) How about consolidating descriptions of all procedures
that convert things to a string.  E.g. symbol->string
should be described in the same section as number->string.

Part II: A catalog of Scheme 

   II.5   Symbols                                                
   II.6   Numbers 
   II.7   Vectors
   II.8   Strings                                                
   II.9   String conversions.     <-!
   II.10  The object table                                        
   II.11  Procedures                                             
   II.12  Ports                                                  
   II.13  Input                                                  
   II.14  Output                                                 

2) When I use a one arm if, I am usually writting side effects,
but with a two arm if, I am not.  I suggest these two different
uses be glorified with different names.  In particular, let's
name the one arm if "when".

(if condition consequent alternative)      essential special form
(when condition expr1 expr2 ...)           essential special form

The result of the when is undefined.

3) Since define has two syntaxes, how about giving rec or
named-lambda the same two.  You could drop one of the
special forms as a result.

(named-lambda (name var1 ...) expr ...)              special form
(named-lambda name expr ...)                         special form

4) I think it is great that the value of set! is undefined.

5) What happened to iterate?  I use it much more than I use do.
It would be nice to name it loop, but I'm sure the T people would
object.

6) Macro not defined in the begining of the report.
                                                 v
`pattern                                       macro special form

7) It is excellent that there is an attempt to stop confusing
the empty list with boolean false.

8) The phrase "more inclined to..." does not sound like the kind
of words one should use in a description of eqv?.

be used to compare numbers.  The eqv? procedure is just like eq? 
except that it is more inclined to say that two numbers are the 
same.  

9) Missing predicate: list?.

(list? obj)                                   essential procedure

(define (list? l) (or (pair? l) (null? l)))

10) I was happy to find that property lists are not part of the
definition of symbols.

11) I vote for the long name instead of call/cc.

(call-with-current-continuation f)                      procedure

John

∂21-Mar-85  1554	@MIT-MC:JINX@MIT-OZ 	DRAFT of the Revised Revised Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Mar 85  15:51:13 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 21 MAR 85  18:51:21 EST
Date: 21 Mar 1985  18:49 EST (Thu)
Message-ID: <JINX.12096895077.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   scheme@MIT-MC
Subject: DRAFT of the Revised Revised Report
In-reply-to: Msg of 21 Mar 1985  17:35-EST
      Thu 21 Mar 85 13:35:25 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford


0)	I agree that car, cdr, etc, are poor names, yet I have not
seen good alternatives to them except first and rest, which don't nest
(a la c....r) too well.  I think that their use is so entrenched that
it would be hard to get used to other things.

	Random related comment: A possibility we have not considered
is general-car-cdr:

(general-car-cdr #b1    l) = l
(general-car-cdr #b10   l) = (car l)
(general-car-cdr #b11   l) = (cdr l)
(general-car-cdr #b101  l) = (cadr l)
(general-car-cdr #b110  l) = (cdar l)
etc.

Thus c....r = (lambda (l) (general-car-cdr n l))

Where n = #b1**** with the mapping a->0 b->1

	C...r (except car and cdr) are defined like that in MIT
Scheme.  Note that general-car-cdr is not limited to a length of 4 for
the chain of car-cdrs, and is trivial to implement.

2 & 5)	The reason for not having a different name for the one-armed
IF is that we tried very hard to keep the number of special forms to a
minimum.  Since they are easily distinguished by the number of
subforms, there is no need to add another.  Note that the same
philosophy leads MIT to have named LET, which is exactly (except for
the name) what ITERATE used to be.

3)	I don't think that the syntax (named-lambda name expr) is a
good idea as a substitute for rec.  An extension of rec would allow
something like (rec a-circular-list (cons 'a a-circular-list)) where
there are no lambdas, so named-lambda is inappropriate.

	Note that both rec and named-lambda are optional, so there is
no need to drop any.  Different dialects have preferences for one
over the other, so an arbitrary decision would probably not sit well.

	Note also that MIT Scheme allows also the syntax
(named-lambda ((foo . args1) . args2) . body) =
	(named-lambda (foo . args1) (lambda args2 . body))
	which is not on the report.

9)	I don't think that the list? you propose is missing.  I think
list? should be defined as

(define (list? l)
  (or (null? l) (and (pair? l) (list? (cdr l)))))

, in other words, proper-list?.

	What you define as list? is what we (MIT-Scheme) call
weak-list? which we have never found a real use for.

	I would like to eliminate the confusion about lists.  I
propose that list refer to proper lists, and anything else built out
of pairs be called a pair-graph.  Thus lists are pair-graphs but not
viceversa.  The procedure LIST produces a list, and the procedure
LIST? tests whether an object is one.

∂22-Mar-85  0951	JAR@MIT-MC 	(if a b)
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  09:50:58 PST
Date: 22 March 1985 12:51-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  (if a b)
To: SCHEME @ MIT-MC
In-reply-to: Msg of 21 Mar 1985 17:35:34-EST
      Thu 21 Mar 85 13:35:25 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford

I'm in agreement with John Ramsdell in opposing amputated IF (although I
also agree with Bill Rozas that WHEN is a bad idea).  IF-forms should
always have two arms.  Could someone explain to me again why it is a
good idea?  It complicates the language.  You can always use (COND (test
...)) if you really don't want to write another arm.  And your dialect
can optionally include the amputated variant.  I don't see how one can
simultaneously support (IF A B) and oppose (DEFINE (FOO X) Y).

Jonathan

∂22-Mar-85  1322	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	ASSERT, ports, and NIL 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  13:22:07 PST
Received: from csnet-relay by MIT-MC.ARPA; 22 MAR 85 16:22:23 EST
Received: from ti-csl by csnet-relay.csnet id ac00183; 22 Mar 85 14:11 EST
Date: 22 Mar 1985 1032-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: ASSERT, ports, and NIL
To: Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Fri, 22 Mar 85 10:56 CST

I have some miscellaneous comments on topics raised recently...


1.  I like Will's ASSERT.  I have used the same approach before in
compilers for Pascal and other languages and find that it is quite
appropriate for both the programmer and a dataflow-oriented optimizer.


2. I like PORT.  My Webster's includes the following definitions: 

   (2a) an opening for intake or exhaust of a fluid ...
   (2c) a place of access to a system

This is close enough to the concept we have in mind.  Frankly, "raft" seems
too whimsical for a language that deserves to be taken seriously.


3. I hate NIL.  However, I have a problem of great practical significance
to our work that I'd like help with.  As much as I abhor it personally,
Common Lisp equates the empty list, the logical <false> value, and the
symbol NIL.  Here at TI's Computer Science Lab, we are building
experimental multi-lingual program development environments for various
machines (including our Explorer Lisp machine) in which Scheme, Common
Lisp, Prolog, and other languages need to co-exist.  I see no practical way
to avoid defining our Scheme's #!NULL and #!FALSE as anything other than
the symbol NIL.  Otherwise the two languages cannot share list data.  If
anyone has a good general solution to this problem, I'd like to hear of it.
If not, I ask that this interpretation be permitted by the revised report.
Surely we aren't the only ones interested in multi-lingual issues?

Regards,
David Bartley
-------


∂22-Mar-85  1325	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Revisions to String Proposal 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  13:25:35 PST
Received: from csnet-relay by MIT-MC.ARPA; 22 MAR 85 16:22:54 EST
Received: from ti-csl by csnet-relay.csnet id ag00183; 22 Mar 85 14:13 EST
Date: 22 Mar 1985 1105-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: Revisions to String Proposal
To: CPH%MIT-OZ@mit-mc.ARPA, Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 20-Mar-85 0242-CST
Received: from csl60 by ti-csl; Fri, 22 Mar 85 12:26 CST

I am quite pleased with Chris' revised string proposal.

A minor suggestion -- perhaps the = and < comparators could be made
essential and the <=, >, and >= comparators made optional.

Regards,
David Bartley
-------


∂22-Mar-85  1344	@MIT-MC:GJS@MIT-OZ 	Re: ASSERT, ports, and NIL    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  13:44:42 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 22 MAR 85  16:44:32 EST
Date: Fri 22 Mar 85 16:43:08-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: ASSERT, ports, and NIL
To: Bartley%ti-csl.csnet@CSNET-RELAY.ARPA
cc: scheme@MIT-MC
In-Reply-To: Message from "David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>" of Fri 22 Mar 85 11:32:00-EST

I like "port" too!
-------

∂22-Mar-85  1353	JAR@MIT-MC 	NIL
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  13:53:38 PST
Date: 22 March 1985 16:52-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  NIL
To: Bartley%ti-csl.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of 22 Mar 1985 1032-CST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    Date: 22 Mar 1985 1032-CST
    From: David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    3. I hate NIL.  However, I have a problem of great practical significance
    to our work that I'd like help with.  As much as I abhor it personally,
    Common Lisp equates the empty list, the logical <false> value, and the
    symbol NIL.  Here at TI's Computer Science Lab, we are building
    experimental multi-lingual program development environments for various
    machines (including our Explorer Lisp machine) in which Scheme, Common
    Lisp, Prolog, and other languages need to co-exist.  I see no practical way
    to avoid defining our Scheme's #!NULL and #!FALSE as anything other than
    the symbol NIL.  Otherwise the two languages cannot share list data.  If
    anyone has a good general solution to this problem, I'd like to hear of it.
    If not, I ask that this interpretation be permitted by the revised report.
    Surely we aren't the only ones interested in multi-lingual issues?

I don't think we need to or should allow either false or the empty list
to be a symbol.  In our PDP-10 Maclisp prototype of T, we solved the
inconsistency by doing (REMOB 'NIL).  Maclisp had a symbol NIL, which
was the same as false and the empty list, and T had a symbol NIL
(created, after the REMOB happened, the first time that READ encountered
the sequence "NIL"), which was different from the Maclisp symbol NIL.  T
and Maclisp coexisted happily.  Then we did:

(defun symbol? (x)
  (and x (symbolp x)))

Similarly, in the Common Lisp emulation package in T, we created a
parameter to READ which caused the atom NIL to read in as the empty
list, using the same framework that allows atoms like 1E3 and 5/8 to be
read as numbers instead of symbols.  Then, we emulated Common Lisp
symbols as the union of T symbols and the empty list:

(define (symbolp x)
  (or (symbol? x) (null? x)))

(define (intern x)
  (if (string-equal? x "NIL")				;(no packages)
      '()
      (string->symbol x)))

(define (symbol-name x)
  (xcond ((symbol? x) (symbol->string x))
	 ((null? x) "NIL")))

and so on.

So Common Lisp (with its own environment, syntax table, and read table
distinct from T's) coexisted happily with T.

The much harder problem is emulating the status quo when false and the
empty list are distinguished, but let's not talk about that.

Jonathan

∂22-Mar-85  1835	@MIT-MC:HUDAK@YALE.ARPA 	Re: DRAFT of the Revised Revised Report 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  18:34:52 PST
Received: from yale by MIT-MC.ARPA; 22 MAR 85 21:21:48 EST
Received: by YALE-BULLDOG.YALE.ARPA; 21 Mar 85 21:31:50 EST (Thu)
Message-Id: <8503220231.AA28348@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 21 Mar 85 21:28:34 EST
Subject: Re: DRAFT of the Revised Revised Report
Date: Thu, 21 Mar 85 21:28:35 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Bill Rozas <JINX%MIT-OZ@MIT-MC>
Cc: scheme@MIT-MC
In-Reply-To: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>, 21 Mar 1985  18:49 EST (Thu)

    0) I agree that car, cdr, etc, are poor names, yet I have not
    seen good alternatives to them except first and rest, which don't
    nest (a la c....r) too well.  I think that their use is so
    entrenched that it would be hard to get used to other things.
    
Another possibility is head and tail.  Both of them actually *do*
nest fairly well; for example, according to the following scheme:

    car&cdr     head&tail   first&rest
    ----------------------------------
    caar        hhd         fft
    cadr        htl         frt
    cdar        thd         rft
    cddr        ttl         rrt
    caaar       hhhd        ffft
    caadr       hhtl        ffrt
    cadar       hthd        frft
    caddr       httl        frrt
    ...         ...         ...

My personal preference is head and tail, but anything is better than
car and cdr.

        -Paul

∂22-Mar-85  2049	@MIT-MC:ANDY@SU-SCORE.ARPA 	Re: DRAFT of the Revised Revised Report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Mar 85  20:48:54 PST
Received: from SU-SCORE.ARPA by MIT-MC.ARPA; 22 MAR 85 23:49:16 EST
Date: Fri 22 Mar 85 20:47:41-PST
From: Andy Freeman <ANDY@SU-SCORE.ARPA>
Subject: Re: DRAFT of the Revised Revised Report
To: Hudak@YALE.ARPA
cc: JINX%MIT-OZ@MIT-MC.ARPA, scheme@MIT-MC.ARPA
In-Reply-To: Message from "Paul Hudak <Hudak@YALE.ARPA>" of Fri 22 Mar 85 18:36:19-PST

Actually I prefer car/cdr over head/tail and first/rest because the
former have no outside associations (I've never seen a 7094) and the
latter do.  I then define more appropriate names that reflect the
meaning in the program.  More meaningful (or less ugly) names don't
encourage this.  (I'm not sure about -<>-, etc., but they share the
unnecessary topological connotations of head/tail and first/rest.)

Then again, I don't want my cons operations to suggest that I'm
working on lists, just cons'.  (Someone has already mentioned the
difference between cons? and list?)  Also, car/cdr are nice harmless
bit of history.

-andy
-------

∂24-Mar-85  0007	@MIT-MC:CPH@MIT-OZ  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Mar 85  00:07:05 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 24 MAR 85  03:06:34 EST
Date: Sun, 24 Mar 1985  02:26 EST
Message-ID: <CPH.12097502667.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Hudak@YALE.ARPA, Jinx%MIT-OZ@MIT-MC.ARPA
Cc:   Scheme@MIT-MC
In-reply-to: Msg of 21 Mar 1985  21:28-EST from Paul Hudak <Hudak at YALE.ARPA>

Maybe I'm just being old and tired, but I like CAR and CDR!  I would
be saddened to see them lost in a wave of "modernization".  Would you
consider changing LAMBDA to something else?  I think that CAR, CDR and
CONS have the same historical value (as does COND, I suppose).

Obviously, I like keeping in touch with the past, as long as it
doesn't cloud the thinking of the future.  This doesn't seem to be
such a case; might as well call the operations "0" and "1", if you
want to be really, really efficient.

∂24-Mar-85  0009	@MIT-MC:CPH@MIT-OZ 	Revisions to String Proposal  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Mar 85  00:09:24 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 24 MAR 85  03:06:38 EST
Date: Sun, 24 Mar 1985  02:37 EST
Message-ID: <CPH.12097504585.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: Revisions to String Proposal
In-reply-to: Msg of 22 Mar 1985  12:05-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    Date: Friday, 22 March 1985  12:05-EST
    From: David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    A minor suggestion -- perhaps the = and < comparators could be made
    essential and the <=, >, and >= comparators made optional.

I think that this is quite reasonable -- often I try to code this way.

Although... is the cost of tying up these few identifiers worth the
extra expressive power they may bring?  I think it probably is;
sometimes it seems that one wants to say "(>= ...)" rather than "(not
(< ...))".  The extra symbols will be bound in people's minds whether
or not they are in the "revised revised report" or not.

∂25-Mar-85  1306	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: NIL 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Mar 85  13:06:14 PST
Received: from csnet-relay by MIT-MC.ARPA; 25 MAR 85 15:44:44 EST
Received: from ti-csl by csnet-relay.csnet id ae10480; 25 Mar 85 15:34 EST
Date: 25 Mar 1985 1153-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: NIL
To: JAR@mit-mc.ARPA, Bartley%ti-csl.csnet@csnet-relay.arpa
cc: SCHEME@mit-mc.ARPA, Bartley%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 22-Mar-85 1552-CST
Received: from csl60 by ti-csl; Mon, 25 Mar 85 13:41 CST

Re: Jonathon's suggestion for rationalizing NIL in Common Lisp and () in
    Scheme...

When Common Lisp is implemented on top of Scheme, or at the same time as
Scheme, your second approach is quite workable.  It relies on making the
representation of the empty list suit Scheme's needs and patching up a few
components of Common Lisp so () "looks" like the symbol NIL.  My only
concern here is that I'd like to use the same reader, the same SYMBOL?/
SYMBOLP routine, etc., but I'm willing to give in on those.

The first example you gave, bringing up Scheme (T) on top of Common Lisp
(Maclisp), still has a problem.  If Scheme is introduced into a system in
which the idea that NIL=='NIL=='() is deeply ingrained (e.g. in microcode),
then I see no way to allow a user to jump back and forth between processes
written in the two languages and which must share the same list data,
without making 'NIL=='().

I intend to make new systems conform along the lines you suggest.  However,
I still would like a multi-lingual implementation built on an existing Lisp
system to be allowed by the standard.

Regards,
David Bartley
-------


∂25-Mar-85  1443	@MIT-MC:linus!ramsdell@mitre-bedford 	ITERATE
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Mar 85  14:43:21 PST
Received: from mitre-bedford by MIT-MC.ARPA; 25 MAR 85 17:43:15 EST
Date: 25 Mar 1985 17:36:35-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA25113; Mon, 25 Mar 85 08:01:59 est
Date: Mon, 25 Mar 85 08:01:59 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503251301.AA25113@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: ITERATE

If named LET is to replace ITERATE, that is fine with me.
Please make it an essential form.
John

∂25-Mar-85  1757	@MIT-MC:HUDAK@YALE.ARPA 	CAR and CDR again   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Mar 85  17:57:48 PST
Received: from yale by MIT-MC.ARPA; 25 MAR 85 20:58:07 EST
Received: by YALE-BULLDOG.YALE.ARPA; 24 Mar 85 19:54:45 EST (Sun)
Message-Id: <8503250054.AA23410@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Sun, 24 Mar 85 20:00:23 EST
Subject: CAR and CDR again
Date: Sun, 24 Mar 85 20:00:25 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: CPH%MIT-OZ@MIT-MC
Cc: Scheme@MIT-MC, Jinx%MIT-OZ@MIT-MC
In-Reply-To: CPH%MIT-OZ@MIT-MC.ARPA, Sun, 24 Mar 1985  02:26 EST

    Maybe I'm just being old and tired, but I like CAR and CDR!  I
    would be saddened to see them lost in a wave of "modernization".
    Would you consider changing LAMBDA to something else?  I think
    that CAR, CDR and CONS have the same historical value (as does
    COND, I suppose).
    
LAMBDA derives from the Lambda Calculus, where the association with
lambda expressions is clear.  CAR and CDR derive from obscure machine
features whose meaning is not clear.  CONS is not so bad because it
is short for CONSTRUCT, although PAIR would probably be better.

    Obviously, I like keeping in touch with the past, as long as it
    doesn't cloud the thinking of the future.  This doesn't seem to be
    such a case; might as well call the operations "0" and "1", if you
    want to be really, really efficient.
    
Efficiency, of course, is not the rationale for any of this.  It's
choosing a name that makes sense.  Why did we choose names like WALK
instead of the "traditional" MAPC or MAPCAR or whatever?  Some people
probably feel as bad about loosing those as they would for CAR and CDR.

However, I'm not one to stand in the way of preserving history!  I was
curious to see how people felt though, and wanted to see how far Essential 
Scheme's modernization effort, which does exist, was willing to go.

        -Paul

∂25-Mar-85  1852	GJC@MIT-MC 	NIL, experience with VAX-NIL, or NIL is nothing to worry about.
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Mar 85  18:42:39 PST
Date: 25 March 1985 21:43-EST
From: George J. Carrette <GJC @ MIT-MC>
Subject:  NIL, experience with VAX-NIL, or NIL is nothing to worry about.
To: Bartley%ti-csl.csnet @ CSNET-RELAY
cc: JAR @ MIT-MC, SCHEME @ MIT-MC
In-reply-to: Msg of 25 Mar 1985 1153-CST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

I was able to put a rational, i.e. (NOT (EQ 'NIL '())), scheme on
top of both VAX-NIL and LMI Release 2.0, both of which are common-lisp.
In fact, in the inner guts of VAX-NIL we have that () is not a symbol,
and the first distributed versions of NIL (SYMBOLP ()) => (),
but peer presure forced us (at that time Glenn Burke and myself) to
toe-the-line and change, if not the guts, but what the user sees
in the way of a type scheme. 

One argument TYPEP is not supported in common-lisp, so the following
output from VAX-NIL should not be suprising:
 (TYPEP ()) => NULL
 (TYPEP 'FOO) => SI:NON-NULL-SYMBOL
 (TYPEP '(FOO)) => SI:SIMPLE-CONS

Of course (SYMBOLP X) <==> (TYPEP X 'SYMBOL) 
   <==> (TYPEP X '(OR NULL SI:NON-NULL-SYMBOL)).
LISTP is then (TYPEP X '(OR NULL SI:SIMPLE-CONS SI:EXTENDED-CONS)).
The SI:EXTENDED-CONS is something GSB put in for BRANDX, (remember hunks?)
but lets not get into that.

There are of course special type masks cleverly arranged to be used with the
VAX instructions for doing these type unions, so that the most useful cases
of two-argument TYPEP are in-line-coded.

The inner workings of the microcoded lisps such as on the LMI LAMBDA
and TI EXPLORER play similar hacks with NIL. Its just one of those
things. Unfortunately the Common-Lisp committee, of which I felt like
an out-gunned member, had the "guts" to change MEMBER, ASSOC, EQUAL,
*, /, +,↑, but not to address this NIL thing.

If you reread JAR's analysis, and I hope I have provided some hints
into the inner workings of some of the base lisps in question, then
you should see what he is talking about.


∂26-Mar-85  1439	@MIT-MC:linus!ramsdell@mitre-bedford 	WHEN   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  14:38:06 PST
Received: from mitre-bedford by MIT-MC.ARPA; 26 MAR 85 17:38:09 EST
Date: 26 Mar 1985 17:36:00-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA09491; Tue, 26 Mar 85 09:43:17 est
Date: Tue, 26 Mar 85 09:43:17 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503261443.AA09491@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: WHEN

OK, so WHEN is a bad idea.  However, I agree with
Jonathan that one armed IF is a bad idea.
John

∂26-Mar-85  1444	@MIT-MC:linus!ramsdell@mitre-bedford 	LIST?  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  14:41:00 PST
Received: from mitre-bedford by MIT-MC.ARPA; 26 MAR 85 17:38:57 EST
Date: 26 Mar 1985 17:36:04-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA09666; Tue, 26 Mar 85 09:54:52 est
Date: Tue, 26 Mar 85 09:54:52 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503261454.AA09666@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: LIST?
Cc: ramsdell

I thought LIST? would be a good name for the predicate
that returns true to the objects generated by LIST, 
just an VECTOR? returns true to the objects generated
by VECTOR and PAIR? returns true to the objects generated
by PAIR ... eh ... CONS.  Opps! Nevermind.
John
PS Maybe STRING should take a variable number of characters
and returns a string.
(define (string . chars) (list->string chars))

∂26-Mar-85  1501	@MIT-MC:linus!ramsdell@mitre-bedford 	function names.  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  15:01:35 PST
Received: from mitre-bedford by MIT-MC.ARPA; 26 MAR 85 17:39:48 EST
Date: 26 Mar 1985 17:36:09-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA09753; Tue, 26 Mar 85 10:00:27 est
Date: Tue, 26 Mar 85 10:00:27 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503261500.AA09753@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: function names.

It is clear no agreement can be reached about CAR and CDR.
I withdraw the suggested name changes except for:
MAPCAR  =>  MAP and
MAPC    =>  WALK.
Is there disagreement here?
John

∂26-Mar-85  1659	@MIT-MC:KMP@SCRC-STONY-BROOK 	function names.
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  16:59:45 PST
Received: from SCRC-STONY-BROOK by MIT-MC via Chaosnet; 26 MAR 85  19:59:59 EST
Received: from SCRC-RIO-DE-JANEIRO by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 203900; Tue 26-Mar-85 18:28:31-EST
Date: Tue, 26 Mar 85 18:28 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: function names.
To: linus!ramsdell@MITRE-BEDFORD.ARPA, scheme@MIT-MC.ARPA
In-Reply-To: <8503261500.AA09753@linus.UUCP>
Message-ID: <850326182851.4.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>

    Date: Tue, 26 Mar 85 10:00:27 est
    From: linus!ramsdell (John D. Ramsdell)
    Message-Id: <8503261500.AA09753@linus.UUCP>
    Subject: function names.

    It is clear no agreement can be reached about CAR and CDR.
    I withdraw the suggested name changes except for:
    MAPCAR  =>  MAP and
    MAPC    =>  WALK.
    Is there disagreement here?

I support these name changes (perhaps not surprisingly since
I'm partly responsible for them being that way in T). For those
who are curious about the justification for the MAPCAR->MAP change:

 * MAP is nicely generic. You can't later extend MAPCAR to
   work on general structures like matrices without having to
   apologize for the fact that "successive cars of a matrix"
   is not as meaningful as it is for lists.

 * Whenever anyone complained to me that MAP had another 
   meaning and that people would be confused, I would take
   them by the arm and drag them into the office of an
   unsuspecting person to whom I would say: "Please write
   an expression on the board which maps a function F across
   a list L." The person would -always- write
     (MAPCAR F L)
   No one -ever- wrote
     (MAP F L)
   The reason is that MAP is so uncommon that no one even 
   bothers to verbally distinguish it from MAPCAR. You have to
   say "Please write an expression which calls the function MAP
   on arguments which are the function F and the list L." to get
   the other behavior. From this I conclude that it is "natural"
   for the MAPCAR operation to be called MAP.

The arguments for MAPC->WALK are these:

  MAPCAR returns a value which is     intended to be used.
  MAPC   returns a value which is not intended to be used.

  MAPCAR takes a function which is not intended to have a side-effect.
  MAPC   takes a function which is     intended to have a side-effect.

  These two functions have little more in common than the fact
  that their first arg is a function and the second is a list.

  Also, the "C" is pretty random (presumably deriving from the "CAR"
  in MAPCAR). As with MAPCAR, if MAPC were ever extended to map across
  (notice I'm using the word "map" and you -know- what I mean) matrices,
  arrays, vectors, etc. then again the "C" would be still harder to
  explain.

  So we wanted something that connoted `visiting elements' but not 
  a priori constraining the way those elements were enumerated and
  not connoting any idea of return value. WALK was chosen because it's
  short, sounds like what it does ("walks around in structures"), etc.

By the way, T uses MAPCDR and WALKCDR to mean the "less common" variants
(MAPLIST and MAP, respectively, so you don't have to look them up). The
fact that the names are longer is appropriate (common things should get
the short names), as is the fact that the term CDR is included (since
these don't make sense to generalize to non-CDRable things (although if
you generalized CDR, they would make sense and their name would still
be fine)).

To help with this convention, T renames Lisp's traditional LAST function
to LASTCDR, so what is sometimes called LASTCAR can be called LAST (for
naming consistency with MAP/MAPCDR, WALK/WALKCDR, NTH/NTHCDR).

It is this sort of regularization of naming which has led users of T to
spontaneously send fan mail saying how much they like the clarity of
expression the new names encourage. (Most other languages I've seen get
mostly gripes about naming and little or no praise.) What gripes we get
are usually nitpicky things where users (having decided things are really
winning) want to encourage us to go the rest of the way toward making
the naming consistent in the places where we hesitated to make choices
which would clearly have made the language even more regular. Almost no
one has complained of missing an old name (especially since for the cases
where they care, it's so easy to define synonyms).

-kmp

∂26-Mar-85  1703	@MIT-MC:KMP@SCRC-STONY-BROOK 	How to let macros work without defining what a macro is...  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  17:03:06 PST
Received: from SCRC-STONY-BROOK by MIT-MC via Chaosnet; 26 MAR 85  20:00:04 EST
Received: from SCRC-RIO-DE-JANEIRO by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 203911; Tue 26-Mar-85 18:59:50-EST
Date: Tue, 26 Mar 85 19:00 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: How to let macros work without defining what a macro is...
To: Scheme@MIT-MC.ARPA
cc: KMP@SCRC-STONY-BROOK.ARPA
Message-ID: <850326190013.5.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>

Even though it was not possible to agree on how macros
should be specified in Scheme, I believe it important
that they be provided in some form in all implementations
and have a proposal for a semi-invisible way to do this.

(PRIMITIVE-SYNTAX-EXPAND form)		required

 Takes any form and returns a form which is guaranteed
 not to have any syntax other than that required by
 the language.

 This function signals an error if it receives a form
 which is a user-defined macro. (Hence, this function is
 for writing code which is defined only over portable 
 code). The fact that it only allows "primitive" macros
 to be expanded is what makes it not need an ENV argument,
 since the primitive language does not allow one to
 change the set of special forms.

 Actually, there are two variations of this proposal which
 are probably consistent. One says that it expands all 
 levels; the other says that it expands just one level.
 I think it really doesn't matter. For consistency with
 SYNTAX-EXPAND below, let's assume it doesn't recurse into
 the form.

The intent is (though this is not part of the proposal)
that languages providing a macro facility would have a
function:

(SYNTAX-EXPAND form env)		optional

 Takes any form and a syntax environment and returns
 a form which has no other syntax than lisp syntax.

 This form will expand macros and call PRIMITIVE-SYNTAX-EXPAND
 if the underlying representation makes that necessary. 
 The result should be a form which contains only primitive forms.

This would allow us to define system extensions which we could
-describe- as macro translations without telling users how those
things were defined. Eg, they might be macros or they might be
special forms. Consider that (function/macro names in this example
being hypothetical, but you'll get the idea I hope):

 (WITH-OPEN-FILE (STREAM-VAR FILE-NAME . OPTIONS) . BODY)

might be defined to the user to "be the same as":

 (CALL-WITH-OPEN-STREAM (LAMBDA (STREAM-VAR) BODY) FILE-NAME . OPTIONS)

and

 (PRIMITIVE-SYNTAX-EXPAND 
    '(WITH-OPEN-FILE (OUTSTREAM "MY.FILE" 'OUT)
       (PRINT "Hi there." OUTSTREAM)))

would be defined to return

 (CALL-SYNTAX-EXPAND (LAMBDA (OUTSTREAM) (PRINT "Hi there." OUTSTREAM))
		     "MY.FILE" 'OUT)

regardless of whether the system actually did that expansion when it 
ENCLOSEd the form...

This proposal basically gives the user the ability to maintain the
illusion that there are a fixed set of special forms when he does
code-manipulation even if we later decide that a few extra special forms
would be a good idea. eg, WHEN, UNLESS, etc. would not burden code-walking
writers since (PRIMITIVE-SYNTAX-EXPAND form) would know about those
forms and how to magically make them into something meaningful like COND
or IF (are they both primitive? they wouldn't have to be under this proposal).

This also allows implementations to add new special forms which are not
in standard Scheme but which are still handleable by standard Scheme.

Note well that programs which expect to work on code which might call
user-defined macros would HAVE TO use SYNTAX-EXPAND and could not use
PRIMITIVE-SYNTAX-EXPAND even if PRIMITIVE-SYNTAX-EXPAND would appear to
work, since PRIMITIVE-SYNTAX-EXPAND should NOT be sensitive to any
redefinitions of system primitive special forms that extended Scheme
implementations might allow. That is, if a dialect allowed
 (DEFINE-SYNTAX (IF ...) ...variant-definition...)
then
 (SYNTAX-EXPAND '(IF ...)) should get the variant expansion but
 (PRIMITIVE-SYNTAX-EXPAND '(IF ...)) should get the "standard expansion".
This is completely necessary in order for any of this proposal to make sense.

∂26-Mar-85  1802	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Missing CSNET messages 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  18:02:33 PST
Received: from csnet-relay by MIT-MC.ARPA; 26 MAR 85 20:56:28 EST
Received: from ti-csl by csnet-relay.csnet id ab19022; 26 Mar 85 20:19 EST
Date: 26 Mar 1985 1637-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Missing CSNET messages
To: Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa, 
    Scheme.users%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Tue, 26 Mar 85 19:16 CST

A failure at our end caused TI-CSL to miss messages directed to it
yesterday.  Would anyone who sent a message to me (Bartley@TI-CSL) or
indirectly to us through Scheme@MIT-MC please resend their messages?

Senders include:

	MW@Brandeis
	JAR@MIT-MC
	linus!ramsdell...
	the CSNET postmaster
	GJC@MIT-MC
	HUDAK%YALE@MIT-MC.ARPA

I don't know how to interpret some of the addresses that failed.  We
apparently received messages for "Scheme@Users" which were rejected.  Our
local Scheme group mailing list is Scheme.Users@TI-CSL, if that's what
you're looking for.

Regards,
David Bartley
-------


∂26-Mar-85  1839	@MIT-MC:GJS@MIT-OZ 	car/cdr   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Mar 85  18:39:40 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 26 MAR 85  21:39:06 EST
Date: Tue 26 Mar 85 21:37:53-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: car/cdr
To: hudak@YALE.ARPA
cc: scheme@MIT-MC

I dunno if I ever responded to you about this, but I really like
CAR, CDR, CADADR and all the rest.  The special advantage is that they
can be pronounced, so I can say them fast over the phone to someone and
they can be expected to understand what I said.  Imagine having to say
"First of Rest of First of Rest" when one can say "CADADR"... The key is
that combinations of "A" and "D" are not tongue-twisters.

I think that this is the only name convention I really am attached to, and
it is NOT for historical (hysterical?) reasons, but pragmatic ones.
-------

∂27-Mar-85  0212	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  DRAFT of the Revised Revised Report
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  02:12:11 PST
Received: from csnet-relay by MIT-MC.ARPA; 27 MAR 85 05:12:36 EST
Received: from unc by csnet-relay.csnet id ac21376; 27 Mar 85 5:04 EST
Received: by unc (4.12/4.7) id AA21906; Wed, 27 Mar 85 01:25:03 est
Date: Wed, 27 Mar 85 01:25:03 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503270625.AA21906@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  DRAFT of the Revised Revised Report

    2 & 5)	The reason for not having a different name for the one-armed
    IF is that we tried very hard to keep the number of special forms to a
    minimum.  Since they are easily distinguished by the number of
    subforms, there is no need to add another.  Note that the same
    philosophy leads MIT to have named LET, which is exactly (except for
    the name) what ITERATE used to be.

I used to have both one-armed "if" and named "let" in my system.  I got
tired of explaining that the return value of "if" is defined if there
are two arms but undefined if there is one arm.  With "let", I got
tired of explaining that it creates simple bindings in the one case
and performs looping/recursion in the other.  "let" is such an important
special form that it is inappropriate to give it two such different
meanings.

If you have two syntaxes for one special form, then you have two special
forms.  The only difference is that they are distinguished by more than
just the syntax keyword.  If one of the two is a natural extension of the
other, fine, otherwise the situation leads to unwarranted confusion.
(The "number of subforms" is an easy distinction for a compiler, but not
always for the eye.  I prefer the distinction to be more obvious.)

Incidentally, I had named "let" in my system to correspond to named
"lambda", so named "let" was easy to explain in terms of named "lambda".
Of course, the destructuring lambda-list syntax blew that away.


Conclusions:

I prefer to include "when" and "unless".  Cond is not an acceptable
alternative; it is best used to reduce nesting in long sequences of
"if-then-else-if" expressions.  While we're at it, I'd like to see
both "cond" and "case" require an "else" clause.

I also prefer the name "recurse" to "iterate" or named "let", and would
like to see it required by the standard.

..Kent

∂27-Mar-85  0638	@MIT-MC:JINX@MIT-OZ 	function names.    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  06:38:20 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  09:38:40 EST
Date: 27 Mar 1985  09:37 EST (Wed)
Message-ID: <JINX.12098367479.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   linus!ramsdell@MITRE-BEDFORD.ARPA, scheme@MIT-MC.ARPA
Subject: function names.
In-reply-to: Msg of 26 Mar 1985  17:36-EST
      Tue 26 Mar 85 10:00:27 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford

	What does WALK stand for?  Something like FOR-EACH would be
better (except that it suggests the opposite order for the arguments).

	WALK suggests something that performs a tree walk to me.

∂27-Mar-85  0709	@MIT-MC:JINX@MIT-OZ 	DRAFT of the Revised Revised Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  07:09:34 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  10:09:51 EST
Date: 27 Mar 1985  10:08 EST (Wed)
Message-ID: <JINX.12098373078.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Kent Dybvig <dyb%unc.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: DRAFT of the Revised Revised Report
In-reply-to: Msg of 27 Mar 1985  01:25-EST from Kent Dybvig <dyb%unc.csnet at csnet-relay.arpa>


(define (number-of-special-forms-in-standard date)
  (expt 2 (date->number date)))

Now seriously,

	Named let corresponds to named-lambda in the same way that let
corresponds to lambda.  If argument list destructuring is not a
problem for let, it is not a problem for named let.  If it is, the
only "destructuring" allowed in lambda is for &rest arguments (dot
notation).  The syntax for LET can be extended to accept rest
arguments:

	Note: Each of the subforms of the binding list of a let must be a
list whose CAR is the identifier and whose CADR is the expression
whose value the identifier will receive.  Thus the syntax can be
extended to the following:

	(let ((<identifier 1> <exp 1>)
	      .
	      .
	      .
	      (<identifier n> <exp n>)
	      <rest identifier>				; Note: no parens
	      <rest exp 1>
	      .
	      .
	      .
	      <rest exp m>)
	  <body>)

	The rest identifier can be recognized by not being in a list,
and all forms following it are the expressions whose values will be
collected into the &rest list.

	I'm not advocating for this extension in the standard, but any
implementation which wants named-let can easily extend the syntax for
let and named-let so that this "destructuring" is provided.

	You may be right in that this means that there are 2 special
forms with the same keyword, but that's alright with me.  I don't want
to have to remember 50 thousand different identifiers which are
"special" to ths system, and I cannot use as identifiers in portable
code since I don't know what happens in all implementations when a
lambda-parameter attempts to shadow them.

	I have no problems recognizing one-armed ifs.  They only
appear in the middle of sequences (sorry, begins) and indentation
allows me to see whether there is a second arm or not.


∂27-Mar-85  0722	@MIT-MC:JINX@MIT-OZ 	How to let macros work without defining what a macro is... 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  07:21:59 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  10:20:54 EST
Date: 27 Mar 1985  10:19 EST (Wed)
Message-ID: <JINX.12098375135.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: How to let macros work without defining what a macro is...
In-reply-to: Msg of 26 Mar 1985  19:00-EST from Kent M Pitman <KMP at SCRC-STONY-BROOK.ARPA>

	This assumes that all macros work at the s-expression level,
which is not true in our implementation.  The only way to provide both
(especially syntax-expand) in all cases would be to fully reduce to
s-code and then invert to s-expressions.  This would imply full
(recursive) expansion always.

	In our system macros translate from s-expressions to s-code.
There are a few utilities, however, to emulate s-expression level
macros built on top of this.  But macros like COND, LET, etc are never
translated at the s-expression level.

∂27-Mar-85  0727	@MIT-MC:JINX@MIT-OZ 	LIST? -- LIST 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  07:27:18 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  10:24:48 EST
Date: 27 Mar 1985  10:23 EST (Wed)
Message-ID: <JINX.12098375866.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Subject: LIST? -- LIST
To:   linus!ramsdell@MITRE-BEDFORD.ARPA, SCHEME@MIT-MC

	LIST? will return true of those objects generated by LIST.

	That is precisely the case.  The previous proposed definition
for LIST? would return true of things which are not propoer lists, but
LIST can only generate proper lists.  Since there is no way (that I
know of) of knowing whether a paricular pair-tree was created by a
call to LIST or not (besides the fact that it seems undesirable), the
only way to make this consistent is for LIST? to return #!true only on
proper lists.

∂27-Mar-85  0808	GJC@MIT-MC 	plea for macros   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  08:08:32 PST
Date: 27 March 1985 11:08-EST
From: George J. Carrette <GJC @ MIT-MC>
Subject: plea for macros
To: SCHEME @ MIT-MC

How about biting the bullet and admitting macros in a way such that
the language can have only one special form: LAMBDA, and all other
forms are defined as macros, even "IF". (To repeat something I've
either seen in a scheme paper or a scheme compiler:
 (IF A B C) => (*IF A (LAMBDA () B) (LAMBDA () C)), where *IF is
a hand-coded SUBR). The proper packaging of macros and macro namespaces
would put a lot of budding languages designers amoung us out of business.
Think of scheme as an OEM oriented language. The designers can supply
not much more than the primitives used a "Structure and Interpretation"
the essential ideas and tools, then all manner of interesting (or not)
things can be built on these without being the responsibility of
the designer.

The fact is that there are very large, useful, and even intrinsically
interesting lisp programs that are built on very few primitives. Case
in point: Macsyma. In order to do Macsyma in what common-lisp provides
I had to write my own versions of: GET, EQUAL, ASSOC, PUTPROP, +, -, /, ↑, \,
MEMBER, MAP, MAPLIST. One page of code, big deal.

∂27-Mar-85  1123	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: ASSERT, ports, and NIL  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  11:23:41 PST
Received: from csnet-relay by MIT-MC.ARPA; 27 MAR 85 14:24:01 EST
Received: from ti-csl by csnet-relay.csnet id ac23602; 27 Mar 85 14:14 EST
Date: 27 Mar 1985 1038-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: ASSERT, ports, and NIL
To: Bartley%ti-csl.csnet@csnet-relay.arpa, Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 22-Mar-85 1032-CST
Received: from csl60 by ti-csl; Wed, 27 Mar 85 12:16 CST

I'd like to clarify my dilemma concerning NIL.  Jonathon Rees has shown,
correctly, that one has no problem meeting both the Common Lisp and
standard Scheme specifications for the empty list when the Scheme developer
is able to affect the implementation of both languages.  In that case, the
underlying representation for the empty list is arbitrary (call it #!NULL).
The Scheme reader treats the token NIL as a symbol.  The Common Lisp reader
interns the token NIL as #!NULL, and such critical routines as SYMBOLP and
INTERN are modified to pretend that the value named #!NULL is a symbol.

The situation I am concerned about is one in which Scheme is being
implemented on top of an existing Lisp system which we are unable to
modify.  This is clearly a short term problem, but quite real while it
lasts, and surely not unique to us.  For example, it is a problem with
Scheme implementations in Franz Lisp, and in ZetaLisp on Lisp Machines with
()==NIL hardwired into microcode.

Let me walk through an instance of the problem.  Assume an existing Lisp in
which ()==NIL.  In Lisp, generate a list; the list will be "terminated"
with the symbol NIL in the last CDR.  Pass the list to a Scheme routine,
which cdr's down it until it reaches -- what?  Unless #!NULL==NIL, Scheme
can't detect the end of the list with a simple EQ? test.  Sharing of list
data between the two languages is effectively ruled out.

Again: I'm not arguing that allowing #!NULL==NIL is "good," because it
certainly isn't.  I'm just asking for help in overcoming it and, barring a
true solution, insertion of appropriate language in the revised revised
Report acknowledging that it may be a necessity in some implementations.

Alternatively, we could consider such an implementation a "near Scheme" and
take the long term view that it is an interim step towards a "true Scheme."
My purpose here is to raise the issue and possibly find a solution I hadn't
thought of, not to quibble over legalities.

Regards,
David Bartley
-------


∂27-Mar-85  1140	@MIT-MC:ADAMS@YALE.ARPA 	Re:  DRAFT of the Revised Revised Report
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  11:40:20 PST
Received: from yale by MIT-MC.ARPA; 27 MAR 85 14:40:41 EST
Received: by YALE-BULLDOG.YALE.ARPA; 27 Mar 85 14:30:17 EST (Wed)
Message-Id: <8503271930.AA25200@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Wed, 27 Mar 85 14:28:58 EST
Subject: Re:  DRAFT of the Revised Revised Report
Date: Wed, 27 Mar 85 14:29:07 EST
From: Norman Adams <Adams@YALE.ARPA>
To: Kent Dybvig <dyb%unc.csnet@CSNET-RELAY>
Cc: scheme@MIT-MC
In-Reply-To: Kent Dybvig <dyb%unc.csnet@csnet-relay.ARPA>, Wed, 27 Mar 85 01:25:03 est

    I also prefer the name "recurse" to "iterate" or named "let", and would
    like to see it required by the standard.

As far as I can tell, "recurse" is not (yet!) an English word.  I think 
"recur" would be better, though even that doesn't seem great.   
    
-------

∂27-Mar-85  1143	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	Re: Draft of R.R. Report  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  11:43:12 PST
Received: from csnet-relay by MIT-MC.ARPA; 27 MAR 85 14:41:26 EST
Received: from indiana by csnet-relay.csnet id ac23683; 27 Mar 85 14:32 EST
Date: Wed, 27 Mar 85 13:22:21 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA04491; Wed, 27 Mar 85 13:22:21 est
To: scheme@mit-mc.ARPA
Subject: Re: Draft of R.R. Report

We are quite pleased with the report.  Its synthesis is particularly
remarkable given the considerable diversity of opinion expressed on the
net.  Asside from a few bugs and editorial suggestions communicated
directly to Will (the most significant of which was that we agreed
CALL-WITH-CURRENT-CONTINUATION was essential), our only remaining
difficulties with the proposal are reflected in the following opinions.


Given (1) the failure to specify under what circumstance an escape
procedure invocation will result in closing a port opened with
CALL-WITH-INPUT-FILE or CALL-WITH-OUTPUT-FILE, and (2) the optional
nature of the explicit open and close operations, the result is that
portable code can not be written for applications in which ports must
be closed (often the case with todays operating systems) and escape
procedures must be used (as in a coroutine application).  The simplest
solution is to make the open and close operations essential and the
call-with operations optional.  (In general, if an essential feature
can not be fully specified, it should always be possible to program
around the uncertainty.) If there is some reason why the open and close
operations can not be essential (which shouuld be spelled out in a
rationale statement), then the call-with functions should close files
*only* when they return to the continuation of their invocation.  It
would then be possible to define the open and close operations using
call-with functions and devious application of escape procedures.

READ-CHAR-READY? is more descriptive than LISTEN?.  The failure to
specify what it returns at end of file is most unfortunate.  We
shouldn't waffle just because Common Lisp got it wrong.

If you need to READ with assurance that you won't block, you have to
write your own reader using READ-CHAR-READY?  and READ-CHAR?.  How
about adding READ-READY?, which returns true iff an entire parsable
object can be read without blocking.  (A system that includes READ-ATOM
should also include READ-ATOM-READY?.)

An alternative to this predicate proliferation is to allow all read
functions to return a distinguished object to indicate blocked input,
as they may return a distinguished object to indicate end-of-file.
Then all we need is a single predicate for this object, say HUNG?.

The inclusion of the same numeric order predicates with and without a
"?" looks terrible--as if we couldn't make up our mind, which is what
standardization is all about.  And both forms are essential!  We were
among of those who insisted on the simpler (no ?) forms because that is
what we were accustomed to.  But we'd rather switch than fight if the
result is such conspicuous failure to standardize.  At the very least,
only one form should be essential.  Would anyone else be willing to
switch?

#!TRUE, #!FALSE and #!NULL should not be constants.  They are
sufficiently ugly in programs that an extra quote mark in front is
hardly worse.  If they are required more than occasionally they should
be bound to variables anyway.  Why complicate the spartan syntax of
Scheme with such things?  

#!NULL is unnecessary, for we already have a prefectly good way of
printing and reading the empty list, ().  #!NULL is also misnamed:
traditionally NULL is a predicate and NIL is the empty list.

RECURSE (introduced in Chez Scheme and added to Scheme 84) is much
better than "named let" or ITERATE.  If we can not agree, it would
be better if neither RECURSE nor named let were mentioned in the report;
but if the standard says some implementations permit named let, it
should say others permit RECURSE.

DEFINE!  and DEFREC!  should go away.  (Yes, We were among those who
wanted them originally, but they aren't worth it.) We're not fond of
DEFINE either and wish it could go the same way, or at least be
optional.

NUMBER? is redundant, since all all numbers are complex in the
proposal.  If NUMBER? is included to allow for future generalization
(quaternions?) or other reasons, then the rationale should be stated.

WHEN is better than no one arm conditional.  Having no one arm
conditional is better than having IF's alternative optional.  UNLESS we
are better off without.

The interaction of OBJECT-HASH and OBJECT-UNHASH with garbage
collection should be specified.  If we can't decide, the whole section
should be deleted.

A unary constructor is so fundamental that it is worth standardizing.
It might be called BOX, REF or CELL.  BOX probably would create the
least confusion.  Of course, we would also need associated selection,
mutation and predicate functions.


Chris
Dan


∂27-Mar-85  1207	@MIT-MC:GJS@MIT-OZ 	flames!   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  12:07:38 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  15:06:53 EST
Date: Wed 27 Mar 85 15:05:41-EST
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: flames!
To: scheme@MIT-MC

Apparently everyone is hot-under-the-collar about one-armed IF!
I cannot, for the life of me, see the harm of having one-armed IF.
It is totally unambiguous, and it does not eat up a reserved word,
what is more, it is useful.  The alternative of WHEN is just feeping
creaturism, as far as I can see.

Just to add some fuel to the controversy, let me make a horrifying 
suggestion:

(if p q) should be defined.
   It should return #!true if p is false, and it should return
   the value of q if p is true.  This conflicts with no current
   usage since everyone agrees that one should not use the value
   of a side-effect operation.  On the other hand, it gives IF the
   value of logical implication, in the boolean case -- an often
   useful feature.  For example:

     (if (if p q) r s)

-------

∂27-Mar-85  1242	@MIT-MC:JINX@MIT-OZ 	ASSERT, ports, and NIL  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  12:42:00 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  15:30:35 EST
Date: 27 Mar 1985  15:27 EST (Wed)
Message-ID: <JINX.12098431230.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: ASSERT, ports, and NIL
In-reply-to: Msg of 27 Mar 1985  11:38-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

	I don't understand the problem.

	NULL? is essential, and as far as I know it is the only
appropriate way to detect an empty list.

	How NULL? is implemented (in terms of EQ?, etc) is irrelevant.

	As far as I'm concerned there are multiple list terminators
all of which are NULL?

∂27-Mar-85  1245	@MIT-MC:JINX@MIT-OZ 	Draft of R.R. Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  12:45:10 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 27 MAR 85  15:38:18 EST
Date: 27 Mar 1985  15:36 EST (Wed)
Message-ID: <JINX.12098432860.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Chris Haynes <cth%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: Draft of R.R. Report
In-reply-to: Msg of 27 Mar 1985  13:22-EST from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

	I agree that #!NULL is unnecessary, but I don't agree that
#!FALSE, etc should be quoted or that they should be bound to
variables if used often.  How come you don't ask for 0 to be quoted or
bound to a variable if used often?

	RECURSE has the same bug that ITERATE has.  The name implies a
certain behaviour which the process it develops may not conform to.  In
particular, I usually use named let for loops, but I also use it for
recursive procedures.  The advantage of named let is that its name has
no connotations, and that it reduces the number of "reserved"
keywords.

	How am I supposed to define things if both DEFINE! and DEFINE
go away?

	While I agree that CELLs are nice, why are they neccesary?
They can easily be emulated with pairs, and any implementation which
really uses them can support them optionally.

∂27-Mar-85  1644	@MIT-MC:linus!ramsdell@mitre-bedford 	Scheme names
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  16:44:31 PST
Received: from mitre-bedford by MIT-MC.ARPA; 27 MAR 85 19:44:51 EST
Date: 27 Mar 1985 19:39:08-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA25130; Wed, 27 Mar 85 10:45:05 est
Date: Wed, 27 Mar 85 10:45:05 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503271545.AA25130@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: Scheme names

When is said that I thought one armed IF is a bad idea,
I really meant that having both a one armed IF and a two
armed IF called the same thing is a bad idea.  I can
live without one armed IF because it is trivial to write
the obvious WHEN macro or use COND.  Kent points out that the same
problem occurs with named LET.  Thus I withdraw my support
for named LET syntax, and request ITERATE (maybe called LOOP)
become an essential form.

I would like to echo KMP's statements about regularization of
naming in T.  It is great!  Even with a small programming language
like Scheme, it should be the case that one needs to memorize a
small set of naming rules, from which one can correctly guess the
name of the particular function of interest.  With T, I am noticely
less dependent on having a manual by my side.

I find it hard to believe that no standardization of macros is
attempted by the Scheme Report, and hope that KMP's macro suggestion
is given serious consideration.
John

∂27-Mar-85  1726	JAR@MIT-MC 	NIL, again   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Mar 85  17:26:16 PST
Date: 27 March 1985 20:26-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  NIL, again
To: Bartley%ti-csl.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC

    Date: 27 Mar 1985 1038-CST
    From: David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

    Let me walk through an instance of the problem.  Assume an existing Lisp in
    which ()==NIL.  In Lisp, generate a list; the list will be "terminated"
    with the symbol NIL in the last CDR.  Pass the list to a Scheme routine,
    which cdr's down it until it reaches -- what?  Unless #!NULL==NIL, Scheme
    can't detect the end of the list with a simple EQ? test.  Sharing of list
    data between the two languages is effectively ruled out.

I don't agree that things are hopeless.  I will risk repetition in hope
of promoting understanding; my apologies if this message adds nothing to
what I've already said.  To implement Scheme on top of a Lisp which
identifies #!NULL (i.e. (), false) with Lisp's symbol NIL, create a new,
unique object; call it SCHEME:NIL.  Use this object to implement "the"
symbol NIL for Scheme.  Use the object #!NULL, which in Lisp is a symbol
and in Scheme is not, to represent both the empty list and false in
Scheme.

So you have the following equations:

	Lisp:		     Scheme:
	Symbol		<=>  Symbol-but-not-#!NULL
	SCHEME:NIL	<=>  The symbol NIL
	NIL, ()		<=>  (), #!NULL, #!FALSE

The phrase "the symbol NIL" is confusing.  You need to say either "the
Scheme symbol NIL" or "the Lisp symbol NIL".  Lisp and Scheme may agree
on what the empty list and false are, without agreeing on what "the
symbol NIL" is.

(define (symbol? x)
  (and x
       (or (eq? x 'nil)		;This code is read using the Scheme reader!
	   (lisp:symbolp x))))

(define (symbol->string x)
  (cond ((eq? x 'nil) "NIL")
	((not x) (error ...))
	(else (lisp:symbol-name x))))

(define (string->symbol x)
  (cond ((string-equal? x "NIL") 'nil)
	(else (lisp:intern x *scheme-package*))))

(define (null? x) (lisp:null x))

In Common Lisp, these definitions need not be quite so verbose, if you
arrange for the object SCHEME:NIL to be a Common Lisp symbol whose print
name is "NIL" (not EQ to () !).

I do not believe that you will run into trouble if you take this
approach.  Since the list terminator is the same between Lisp and
Scheme, there is no problem sharing list structure.

If you plan to use the Common Lisp reader to read Scheme expressions,
then you are in a bit of trouble; Common Lisp allows some way to define
octathorp read macros (so you can implement Scheme #!..., #I, etc.), but
no way to influence the atom reader.  But won't you have all sorts of
trouble with numbers if you don't change the atom reader?

I find it hard to believe that you would not be able to make the trivial
required change (the addition of a single COND clause, no more than two
lines of code!).  If this patch is really impossible, and you cannot use
a different reader (another tractable solution), then indeed I agree you
will be forced to equate Scheme's NIL with ().  I'm sure that would be
fine as an interim solution.  The symbol/false distinction is too
useful, and likely to be too ingrained in programs, to permit deviation
from it in the R.R. (although I agree that legalities are not at issue
here).

Jonathan

∂28-Mar-85  0611	@MIT-MC:KMP@SCRC-STONY-BROOK 	How to let macros work without defining what a macro is...  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  06:11:32 PST
Received: from SCRC-STONY-BROOK by MIT-MC via Chaosnet; 28 MAR 85  09:11:51 EST
Received: from SCRC-RIO-DE-JANEIRO by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 204535; Wed 27-Mar-85 19:34:21-EST
Date: Wed, 27 Mar 85 19:34 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: How to let macros work without defining what a macro is...
To: JINX@OZ.MIT
cc: Scheme@MIT-MC.ARPA
In-Reply-To: <JINX.12098375135.BABYL@MIT-OZ>
Message-ID: <850327193441.0.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>

    Date: 27 Mar 1985  10:19 EST (Wed)
    From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>

	    This assumes that all macros work at the s-expression level,
    which is not true in our implementation.  The only way to provide both
    (especially syntax-expand) in all cases would be to fully reduce to
    s-code and then invert to s-expressions.  This would imply full
    (recursive) expansion always.

	    In our system macros translate from s-expressions to s-code.
    There are a few utilities, however, to emulate s-expression level
    macros built on top of this.  But macros like COND, LET, etc are never
    translated at the s-expression level.

No, you missed the point. You can implement these special forms however
you want. What I'm proposing is something that takes forms which may be
in an extended syntax and translates it into a standard syntax.

eg, suppose the only extended forms in some dialect are WHEN and UNLESS.
Regardless of how those are implemented (perhaps directly represented
in S-code, perhaps translated to something else in S-code, whatever),
all you have to provide is (literally) the following function:

(DEFINE (PRIMITIVE-SYNTAX-EXPAND FORM)
  (COND ((ATOM FORM) FORM)
	((EQ (CAR FORM) 'WHEN)
	 `(COND (,(CADR FORM) ,@(CDDR FORM))))
	((EQ (CAR FORM) 'UNLESS)
	 `(COND ((NOT ,(CADR FORM)) ,@(CDDR FORM))))
	(T FORM)))

You never have to call the function internally in the system. It simply
has to be available for users who want to use it. It must be the 
responsibility of system maintainers to keep it up to date so that 
code-manipulating tools can be written which assume a fixed number 
of special forms and new special forms can later be added to standard 
Scheme which do not cause a need to rewrite those tools.

Suppose that the only special forms we could agree on being standard
were LAMBDA, QUOTE, and SETQ. Suppose that someone insisted that 
 (IF X Y Z)
had to be written
 (*IF (LAMBDA () X)
      (LAMBDA () Y)
      (LAMBDA () Z))
and *IF had to be a function, etc. Assume similar rewrites were suggested
for other special forms. Now consider a user program in a particular 
dialect which had extra special forms (eg, DEFINE, COND, ...):

(DEFINE (USED-FREE-IN EXP VAR TAIL?)
  (COND ((ATOM VAR) (EQ EXP VAR))
	(FLAG
	 (COND ((NULL EXP) NIL)
	       ((USED-FREE-IN (CAR EXP) VAR NIL) T)
	       (T
		(USED-FREE-IN (CDR EXP) VAR T))))
	((EQ (CAR EXP) 'LAMBDA)
	 (COND ((MEMQ VAR (CADR EXP)) NIL)
	       (T
		(USED-FREE-IN (CDDR EXP) VAR T))))
	((EQ (CAR EXP) 'SETQ)
	 (OR (EQ EXP (CADR FORM))
	     (USED-FREE-IN (CADDR EXP) VAR NIL)))
	((EQ (CAR EXP) 'QUOTE) NIL)
	(T
	 (USED-FREE-IN EXP VAR T))))

If I didn't blow it, this program "works" on input which contains 
LAMBDA, SETQ, and QUOTE but does not work on input that contains 
COND, etc. It could, however, work on those, too, by simply making it
say:

(DEFINE (USED-FREE-IN EXP VAR TAIL?)
  (LET ((EXP (PRIMITIVE-SYNTAX-EXPAND EXP)))
    (COND ((ATOM VAR) (EQ EXP VAR))
	  (FLAG
	   (COND ((NULL EXP) NIL)
		 ((USED-FREE-IN (CAR EXP) VAR NIL) T)
		 (T
		  (USED-FREE-IN (CDR EXP) VAR T))))
	  ((EQ (CAR EXP) 'LAMBDA)
	   (COND ((MEMQ VAR (CADR EXP)) NIL)
		 (T
		  (USED-FREE-IN (CDDR EXP) VAR T))))
	  ((EQ (CAR EXP) 'SETQ)
	   (OR (EQ EXP (CADR FORM))
	       (USED-FREE-IN (CADDR EXP) VAR NIL)))
	  ((EQ (CAR EXP) 'QUOTE) NIL)
	  (T
	   (USED-FREE-IN EXP VAR T)))))

The user could write PRIMITIVE-SYNTAX-EXPAND himself, but he'd have
to:

 (a) Make sure his understanding of the syntax equivalences was
     letter perfect (the system implementors have a better chance
     of getting this right)

 (b) Update the function every time the dialect changed. ie, adding
     a special form if PRIMITIVE-SYNTAX-EXPAND is not a system primitive
     function is an incompatible change, but is a compatible change
     if PRIMITIVE-SYNTAX-EXPAND is kept in synch with available special
     forms.

It would be possible to have forms which were not translatable. They
should simply be advertised as such and PRIMITIVE-SYNTAX-EXPAND should err
when it sees them so that the user doesn't think he's winning when he's
not.

Does this make it clearer?
-kmp

∂28-Mar-85  0717	@MIT-MC:HUDAK@YALE.ARPA 	IF and WHEN    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  07:17:19 PST
Received: from yale by MIT-MC.ARPA; 28 MAR 85 10:17:42 EST
Received: by YALE-BULLDOG.YALE.ARPA; 28 Mar 85 10:04:59 EST (Thu)
Message-Id: <8503281504.AA07856@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 28 Mar 85 10:02:02 EST
Subject: IF and WHEN
Date: Thu, 28 Mar 85 10:02:05 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: scheme@MIT-MC
Cc: 
Invalid-Addresses: JINX@OZ.MIT.ARPA (?Invalid domain (host))

The issue of IF vs. WHEN came up when this mailing-list was first
set up, at which time I responded in favor of WHEN.  I'd like to say
again why:  when I read other people's code and come across an IF,
I almost always search to see if there is a second arm.  The bad thing
about this is that if I don't see one I look harder, carefully matching
parens, to make sure I didn't miss it.  I don't buy the "indentation"
argument, because one shouldn't trust other people to follow stylistic
conventions.  Simply from a readability standpoint, WHEN is a good
idea, but at least we should require that IF have two arms.

"Feeping creaturism" is not always bad...

        -Paul

∂28-Mar-85  0753	@MIT-MC:JINX@MIT-OZ 	IF and WHEN   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  07:53:38 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 28 MAR 85  10:53:13 EST
Date: 28 Mar 1985  10:52 EST (Thu)
Message-ID: <JINX.12098643202.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Paul Hudak <Hudak@YALE.ARPA>
Cc:   scheme@MIT-MC
Subject: IF and WHEN
In-reply-to: Msg of 28 Mar 1985  10:02-EST from Paul Hudak <Hudak at YALE.ARPA>

	Do you use EMACS?  If so C-M-F (Lisp or SCheme Modes) does the
job when you're confused.  I didn't mean counting parens.

∂28-Mar-85  0803	@MIT-MC:JINX@MIT-OZ 	syntax-expand 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  08:03:50 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 28 MAR 85  11:04:12 EST
Date: 28 Mar 1985  11:02 EST (Thu)
Message-ID: <JINX.12098645186.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Subject: syntax-expand
To:   kmp@MIT-MC
cc:   scheme@MIT-MC


	I don't think you understood my message.  I was not saying
that we shouldn't have them, just that providing single level
expansion (especially for syntax-expand in the presence of macros) may
not be so easy.  Since you left open the possibility for full
expansion or single level, I vote for full expansion.

[KMP: Sorry that you'll get this message 3 times, but I spazzed]

∂28-Mar-85  1303	@MIT-MC:HUDAK@YALE.ARPA 	Re: IF and WHEN
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  13:03:04 PST
Received: from yale by MIT-MC.ARPA; 28 MAR 85 15:59:18 EST
Received: by YALE-BULLDOG.YALE.ARPA; 28 Mar 85 15:45:05 EST (Thu)
Message-Id: <8503282045.AA03847@YALE-BULLDOG.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 28 Mar 85 15:07:00 EST
Subject: Re: IF and WHEN
Date: Thu, 28 Mar 85 15:07:03 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Bill Rozas <JINX%MIT-OZ@MIT-MC>
Cc: scheme@MIT-MC
In-Reply-To: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>, 28 Mar 1985  10:52 EST (Thu)

    Do you use EMACS?

No.  Perhaps I should, but I work on an Apollo.

It occurred to me after sending the message that counting clauses
in an IF is no different than counting them in any other special form,
including bodies of LET, etc.  Somehow it always seems worse for an
IF, though, perhaps because people tend to write one-liners using IF.

BTW, where does JINX%MIT-OZ@MIT-MC come from?  And how does it relate
to JINX@OZ.MIT which used to work but got rejected on my last message?
Is SCHEME@MIT-MC the only relevant mailing-list for these discussions?

        -Paul

∂28-Mar-85  1437	@MIT-MC:linus!ramsdell@mitre-bedford 	Other names for ITERATE    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  14:37:39 PST
Received: from mitre-bedford by MIT-MC.ARPA; 28 MAR 85 17:37:56 EST
Date: 28 Mar 1985 17:36:55-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA06997; Thu, 28 Mar 85 09:27:45 est
Date: Thu, 28 Mar 85 09:27:45 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503281427.AA06997@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: Other names for ITERATE

Here are some synonyms for let that could be 
used as replacements for ITERATE.  Notice they do not
give any connotation on how the named function will be used.

ALLOW
PROVIDE
ENTITLE
FOSTER

I think the following does looks pretty good.

(ALLOW LOOP ((L L) (SUM 0))
  (IF (NULL? L)
      SUM
      (LOOP (CDR L) (+ (CAR L) SUM))))
John

∂28-Mar-85  1511	@MIT-MC:JINX@MIT-OZ 	Other names for ITERATE 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  15:10:55 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 28 MAR 85  18:11:14 EST
Date: 28 Mar 1985  18:10 EST (Thu)
Message-ID: <JINX.12098722943.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   linus!ramsdell@MITRE-BEDFORD.ARPA, scheme@MIT-MC.ARPA
Subject: Other names for ITERATE
In-reply-to: Msg of 28 Mar 1985  17:36-EST
      Thu 28 Mar 85 09:27:45 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford

Why are you not willing to go one step further and notice ALLOW = LET?

∂28-Mar-85  2248	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  flames!   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Mar 85  22:48:48 PST
Received: from csnet-relay by MIT-MC.ARPA; 29 MAR 85 01:49:09 EST
Received: from unc by csnet-relay.csnet id a002999; 29 Mar 85 1:39 EST
Received: by unc (4.12/4.7) id AA03857; Thu, 28 Mar 85 09:35:09 est
Date: Thu, 28 Mar 85 09:35:09 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503281435.AA03857@unc>
To: GJS%MIT-OZ@mit-mc.ARPA, scheme@mit-mc.ARPA
Subject: Re:  flames!

     (if (if p q) r s)

Could of course be written:
     (if (if p q #!true) r s)


"unless" is a handy special form, in addition to "when":
     (unless (zero? x) (set! x (/ 1 x)))
would have to be written as:
     (when (not (zero? x)) (set! x (/ 1 x)))
or (shudder):
     (if (not (zero? x)) (set! x (/ 1 x)))

It has always bothered me that the "else" part was optional
in the one-or-two-armed-if.  Why can't the "then" part be
optional as well?  

"when" and "unless" are clean, simple, and unambiguous.  They
should both be included in the standard.

∂29-Mar-85  0713	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	ITERATE, DEFINE and CELLs 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  07:13:31 PST
Received: from csnet-relay by MIT-MC.ARPA; 29 MAR 85 10:13:30 EST
Received: from indiana by csnet-relay.csnet id aa05046; 29 Mar 85 10:05 EST
Date: Fri, 29 Mar 85 08:49:59 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA00974; Fri, 29 Mar 85 08:49:59 est
To: scheme@mit-mc.ARPA
Subject: ITERATE, DEFINE and CELLs

> 	RECURSE has the same bug that ITERATE has.  The name implies a
> certain behaviour which the process it develops may not conform to.  In
> particular, I usually use named let for loops, but I also use it for
> recursive procedures.  The advantage of named let is that its name has
> no connotations, and that it reduces the number of "reserved"
> keywords.

Recursion subsumes iteration, so RECURSE is a good name even if used for
simple iteration, but ITERATE isn't a good name when its use is not
tail-recursive.  The *disadvantage* of named let is that its name *does* have
connotation, namely local binding and *not* recursion.  Our desire to keep
down the number of keywords should not be at the expense of such confusion.

> 	How am I supposed to define things if both DEFINE! and DEFINE
> go away?

With SET!, provided one assumes that all identifiers are initially bound in
the global environment, or that SET!  can extend the global environment.
With the exception of MIT's Scheme, this is what existing systems do.  If MIT
is unwilling to change this, then we are reluctantly stuck with DEFINE.

> 	While I agree that CELLs are nice, why are they neccesary?
> They can easily be emulated with pairs, and any implementation which
> really uses them can support them optionally.

They take up half as much space as pairs, and have many fundamental uses.
They aren't *absolutely* necessary, but then neither is most of Scheme.

Chris
Dan


∂29-Mar-85  0759	@MIT-MC:dyb%unc.csnet@csnet-relay.arpa 	Re:  Other names for ITERATE  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  07:59:26 PST
Received: from csnet-relay by MIT-MC.ARPA; 29 MAR 85 10:59:38 EST
Received: from unc by csnet-relay.csnet id a005294; 29 Mar 85 10:52 EST
Received: by unc (4.12/4.7)
	id AA07930; Fri, 29 Mar 85 09:08:20 est
Date: Fri, 29 Mar 85 09:08:20 est
From: Kent Dybvig <dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8503291408.AA07930@unc>
To: scheme@mit-mc.ARPA
Subject: Re:  Other names for ITERATE

How about "spiral" or "cycle"?
Spirals can loop back on themselves, or build up in a recursive
fashion, and the name has no other connotation that I know of.
last I heard, spiral was a word in the English language (though
cdr, ref, cond and cons are not).

Cycle is also a word but may have other connotations.


(spiral f ((x l)) (if (null? l) '() (cons (car l) (f (cdr l)))))

(cycle f ((x l)) (if (null? l) '() (cons (car l) (f (cdr l)))))


∂29-Mar-85  0851	@MIT-MC:GJS@MIT-OZ 	WHEN, UNLESS, RECURSE, et. al.
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  08:51:08 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 29 MAR 85  11:49:46 EST
Date: Fri, 29 Mar 1985  11:47 EST
Message-ID: <GJS.12098915510.BABYL@MIT-OZ>
From: GJS%MIT-OZ@MIT-MC.ARPA
To:   scheme@MIT-MC
Subject: WHEN, UNLESS, RECURSE, et. al.


Rules for Scheme standards:

(1) Entities should not be multiplied beyond necessity. -- William of Occam

(2) Special forms should not be multiplied beyond necessity.

(3) Rules for Scheme standard should not be multiplied beyond necessity.


∂29-Mar-85  0949	@MIT-MC:JINX@MIT-OZ 	ITERATE, DEFINE and CELLs    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  09:49:19 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 29 MAR 85  12:49:40 EST
Date: 29 Mar 1985  12:49 EST (Fri)
Message-ID: <JINX.12098926678.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Chris Haynes <cth%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: ITERATE, DEFINE and CELLs
In-reply-to: Msg of 29 Mar 1985  08:49-EST from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>


> Recursion subsumes iteration, so RECURSE is a good name even if used for
> simple iteration, but ITERATE isn't a good name when its use is not
> tail-recursive.  The *disadvantage* of named let is that its name *does* have
> connotation, namely local binding and *not* recursion.  Our desire to keep
> down the number of keywords should not be at the expense of such confusion.

I disagree.  Recursion for me (and most of the MIT-Scheme people) is a
property of a process, not a feature of the particular syntax with
which it was expressed.  If forms like DO loops are allowed, there is
no syntactic recursion and no real recursion.  One can easily imagine
some dual special form which avoids syntactic recursion while
developing a recursive process when evaluated (executed).  RECURSE
(recur) has too many such connotations for me since I view a procedure
as a way of encapsulating a process, and the only interesting thing is
the process, not its syntactic description.  This distinction between
procedure and process developed by it is very important, though
irrelevant in most programming languages (without a notion of
reduction vs. subproblem) but not in Scheme.  It is further expounded
in "Structure and Interpretation ..." section 1.2.1.

> With SET!, provided one assumes that all identifiers are initially bound in
> the global environment, or that SET!  can extend the global environment.
> With the exception of MIT's Scheme, this is what existing systems do.  If MIT
> is unwilling to change this, then we are reluctantly stuck with DEFINE.

SET! has too many connotations of side effects and I'm not willing
to acceptit as the primary definition mechanism.

I don't view definition as a side effect.  Its interactive
implementation involves one, in the same way that the interpreted
implementation of LETREC involve side effects, only because we don't
know how to do it any better.  The side effects do not exist for
internal definitions.  In the same way that the implementation of
LETREC is incomplete (it can only find a fixed point in some cases,
not all, and the others are disallowed or give an error), the
implementation of DEFINE is incomplete.  Its limitations are no worse
than the limitations of LETREC, yet they meet considerable opposition,
which I don't understand.

Purists in MIT-Scheme advocate for DEFINE to signal an error when
attempting to redefine an already existing identifier in a given
environment.  While conceptually this would be not only appropriate
but logical, it has problems in an interactive system when people want
to re-load some code after making some changes to it.  It would be
very cumbersome to have to change all DEFINEs into SET!s (though I
sometimes think this should be the case).  This is the only reason why
we allow "re-definition" of identifiers (again interactive
constraints).

In a given program there should be no redefinitions (I believe that
our "compiler" will complain, but I'm not sure since I never do it),
and definition should occur before assignment or use.  We even have a
stylistic convention (unfortunately not rigidly adhered to) to aid the
user in determining whether the definition is static (the value will
not change), or we are only introducing an identifier for further
assignment.  In the latter case no initial value is given, thus

(define foo)
(set! foo 3)			; Initial value for foo, which will change

Means something quite different from

(define foo 3)			; Foo is supposed to be 3

This corresponds to LSET and DEFINE in T, but not imposed by the
system.

As you can see, in neither case does the definition conceptually
involve a side-effect, since in the second it declares a constant, and
in the first it declares an identifier which can be used in
assignments.  DEFINE is thus purely declarative, as opposed to SET!
which is imperative.  I believe this distinction is very important,
and justifies the keeping of DEFINE (or some such declarative form).

> They take up half as much space as pairs, and have many fundamental uses.
> They aren't *absolutely* necessary, but then neither is most of
Scheme.

I'm willing to accept them in the standard as long as the CELL type
is not required to be disjoint from PAIR (in the same way that
CHARACTER is not required to be disjoint from STRING or INTEGER).
There is actually a reason for this, I can see a few proposed memory
(debugging) utility programs whose implementation depends on the fact
that all pointer objects have at least 2 words of storage, which would
not be the case for CELLS.

If they are addopted I suggest the following names:

(MAKE-CELL VALUE) returns a CELL object with initial content VALUE.

(CELL-CONTENT CELL) returns the content of cell CELL.

(SET-CELL-CONTENT! CELL NEW-VALUE) makes the new content of CELL be
NEW-VALUE.

∂29-Mar-85  0957	@MIT-MC:JINX@MIT-OZ 	WHEN, UNLESS, RECURSE, et. al.    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  09:56:56 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 29 MAR 85  12:57:18 EST
Date: 29 Mar 1985  12:56 EST (Fri)
Message-ID: <JINX.12098928030.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   GJS%MIT-OZ@MIT-MC.ARPA
Cc:   scheme@MIT-MC
Subject: WHEN, UNLESS, RECURSE, et. al.
In-reply-to: Msg of 29 Mar 1985  11:47-EST from GJS

(4) Messages about WHEN, UNLESS, RECURSE, etc should not be multiplied
beyond necessity.

∂29-Mar-85  1214	JAR@MIT-MC 	ITERATE, DEFINE, WHEN, cells, etc.    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  12:13:53 PST
Date: 29 March 1985 14:09-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  ITERATE, DEFINE, WHEN, cells, etc.
To: SCHEME @ MIT-MC
In-reply-to: Msg of Fri 29 Mar 85 08:49:59 est from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

Why are people so hot to change the report?  Many of these questions
(such as that of ITERATE and its alternatives) were discussed last fall,
and we agreed that we couldn't agree, so the features got omitted.  The
report seems mostly fine to me, and given how strongly people feel about
iteration primitives, DEFINE, and everything else, I don't think it's
worth rocking the boat again.  Perhaps not everyone who is participating
in current discussions has an understanding of how strong the
disagreements are, or perhaps they forget that we agreed that
controversial features are to be ommitted, unless their absence gravely
compromises the ability to express programs at all.

If anything, the report should be pruned, not expanded.  It is already
much larger than most of us would like it to be.  My suggestion that
 (IF A B)  be changed from essential to optional was an attempt to remove
something I thought was both redundant and controversial, and I thought
it a reasonable suggestion, for symmetry with the optionality of
 (DEFINE (F X) Y) ; the fact that there's been so much argument just
supports my proposal that it be removed from the essential dialect!  In
any case, I think we should concern ourselves with inconsistencies and
redundancies, not with questions which were settled (by agreeing to not
settle them) long ago.  The most serious omissions (numbers, strings,
and I/O) have already been addressed.  These other features are simply
not in that class (although I suppose that this meta-point is what the
arguments are about, in part).

Please, be conservative, and consider that if you are likely to meet
implacable opposition, it is probably better to be quiet.  If you have a
new proposal which is just so good that you think everyone will like it,
by all means submit it, but remember that most of us are fanatical
minimalists, and have incompatible measures of minimality.  Form models
of other peoples' viewpoints and modify your speeches accordingly.

Please forgive me for this outburst, but I felt things were getting a
bit out of hand.  This is not to say that many recent messages have not
been reasonable and good.

Jonathan

∂29-Mar-85  1238	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	names    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  12:38:02 PST
Received: from csnet-relay by MIT-MC.ARPA; 29 MAR 85 14:41:06 EST
Received: from indiana by csnet-relay.csnet id a006294; 29 Mar 85 14:32 EST
Date: Fri, 29 Mar 85 12:02:05 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA03416; Fri, 29 Mar 85 12:02:05 est
To: scheme@mit-mc.ARPA
Subject: names

With respect to special forms vs procedures, IF vs IF/WHEN/UNLESS, LET vs
LET/ITERATE, and feeping creaturism, please remember that the keywords of
special forms may be reserved in some implementations and thus cannot be
used as variables in portable code.  When I was a Cobol programmer, it
occurred to me that the main reason that experienced Cobol programmers were
so much more productive than inexperienced programmers was that they didn't
have to flip through the list of several hundred reserved words every time
they wanted to name a variable.

Have pity on the poor beginner.  I could probably keep fifty de facto
reserved words in mind as I program, though there are more important things
that I ought to keep in mind instead.  Beginners, however, are likely to
have trouble remembering the twenty or so we already have.

One of the glories of Scheme is that it gives T (and NIL) back to the
programmer.  At last I can use T as a temporary or to stand for time!  Now
they threaten to take away WHEN and ITERATE.  Arise, programmers, and defend
your namespace!


P.S.  I am in sympathy with the idea of making one-armed IF optional rather
than essential.  The one-armed IF that acts like material conditional looks
like a feeping creature to me.

If our strongest disagreements have to do with procedure names, then we've
made real progress.  I think MAP is much nicer than MAPCAR, and I would like
to see it adopted so we can keep up with the rest of the functional
programming community.  MAPC is utterly random, but while WALK is better it
isn't obviously the right thing and it doesn't have MAPC's tradition.
Anyone for STEP, STOMP, JOG, TIPTOE, PROMENADE, TRAVERSE, or VISIT ?

				William Clinger


∂29-Mar-85  1537	@MIT-MC:linus!ramsdell@mitre-bedford 	REC and LETREC   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  15:36:28 PST
Received: from mitre-bedford by MIT-MC.ARPA; 29 MAR 85 18:36:51 EST
Date: 29 Mar 1985 18:36:48-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA19046; Fri, 29 Mar 85 09:08:34 est
Date: Fri, 29 Mar 85 09:08:34 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503291408.AA19046@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: REC and LETREC

An English name for REC is PROCEDURE.  After all, that is
what it returns.  By the way, is the predicate PROCEDURE?
missing?

Could some one explain why LETREC is preferable to LABELS?
If the name LABELS is so bad, let me suggest alternatives:

LABEL
MARK
TAG
NOTE
GIVE
SUPPLY
PROVIDE      ; from the ITERATE suggestion.
ALLOW

John

∂29-Mar-85  1540	@MIT-MC:linus!ramsdell@mitre-bedford 	rationalized names    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  15:39:54 PST
Received: from mitre-bedford by MIT-MC.ARPA; 29 MAR 85 18:37:03 EST
Date: 29 Mar 1985 18:36:51-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA19092; Fri, 29 Mar 85 09:14:58 est
Date: Fri, 29 Mar 85 09:14:58 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503291414.AA19092@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: rationalized names

How about adding a section on naming conventions,
much like the so named section in the T manual.  
Agreeing one these conventions would greatly 
increase program portability.
John

∂29-Mar-85  1545	@MIT-MC:linus!ramsdell@mitre-bedford 	LIST?  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  15:44:57 PST
Received: from mitre-bedford by MIT-MC.ARPA; 29 MAR 85 18:37:51 EST
Date: 29 Mar 1985 18:36:55-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA19122; Fri, 29 Mar 85 09:19:38 est
Date: Fri, 29 Mar 85 09:19:38 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8503291419.AA19122@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: LIST?

Is it agreed that LIST? should be included in the report
and that is should be defined as per Bill Rozas?
Eg. The predicate that returns true to objects generated
by LIST.
John

∂29-Mar-85  1631	@MIT-MC:mw%brandeis.csnet@csnet-relay.arpa 	Other names for ITERATE   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  16:31:18 PST
Received: from csnet-relay by MIT-MC.ARPA; 29 MAR 85 19:31:38 EST
Received: from brandeis by csnet-relay.csnet id ab07489; 29 Mar 85 19:17 EST
Received: by brandeis.ARPA (4.12/4.7)
	id AA03530; Fri, 29 Mar 85 13:37:18 est
Date: 29 Mar 1985 13:30-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: Other names for ITERATE
To: scheme@mit-mc.ARPA
Message-Id: <480969029/mw@brandeis>

How about LABEL?  Except for its (obsolescent) use in Lisp and in
imperative languages, it has no other connotations, and it corresponds
nicely to the purported denotational semantics.  Furthermore, each of
those uses corresponds to a recursive declaration of some sort.
Thus:

(label foo ((x 0)(y 1)(k (lambda (x) x))) blah)

BTW, "recursion" is the noun form of the verb "recur" (to occur again).
[As vision is the noun form of the verb "view"].  So if you verb
"recursion", you should get "recur", not "recurse", as in: "this
function recurs (not recurses) on the cdr of its argument."

-- Mitch


∂29-Mar-85  2135	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	NIL vs ()    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  21:35:34 PST
Received: from csnet-relay by MIT-MC.ARPA; 30 MAR 85 00:35:45 EST
Received: from ti-csl by csnet-relay.csnet id aa08681; 30 Mar 85 0:24 EST
Date: 29 Mar 1985 1355-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: NIL vs ()
To: Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Fri, 29 Mar 85 14:27 CST

Thanks to JAR and GJC, I have a clearer idea of how to avoid the problem
I've raised recently.  This has been one of those things that could be
cleared up in 10 minutes in person, but has been beset with terminology
problems.  I withdraw my request.

Regards,
David Bartley
-------


∂29-Mar-85  2138	@MIT-MC:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	RE: The revised revised Report   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Mar 85  21:38:23 PST
Received: from csnet-relay by MIT-MC.ARPA; 30 MAR 85 00:35:54 EST
Received: from ti-csl by csnet-relay.csnet id ac08681; 30 Mar 85 0:24 EST
Date: 29 Mar 1985 1437-CST
From: David Bartley <Bartley%ti-csl.csnet@csnet-relay.arpa>
Subject: RE: The revised revised Report
To: Scheme@mit-mc.ARPA
cc: Bartley%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Fri, 29 Mar 85 15:00 CST

Here are my votes on some of the issues swirling around the Scheme World
these days...

 -- I strongly prefer the term "port."

 -- I prefer the names CAR and CDR to anything else I've heard.  I am
partly motivated by the desire to woo others away from inferior forms of
Lisp; avoiding such changes may help.

 -- I prefer MAP and WALK to MAPCAR and MAPC.  Common Lisp's MAP is a
generalization of MAPCAR, so I don't see any problem there.  WALK is more
meaningful than MAPC.  WALK should be optional; MAP may be either essential
or optional.

 -- Both IF and WHEN are worthwhile.  "One-armed" IF and WHEN should both
be optional.  I use WHEN exclusively for side effects and the choice of the
name helps clarify my intent.  I don't like UNLESS, because it adds nothing
new, but making it optional is OK by me.

 -- I'd like to modify EQV? slightly to align it with Common Lisp's EQL.
I believe the only difference is that EQL "does the right thing" for
character data objects as well as for numbers.  Does anyone oppose this?

 -- I am worried about PRIMITIVE-SYNTAX-EXPAND.  It "feels" like too
little, too late in the game.  I'd rather allow time for this issue to gel
further.

 -- It has been suggested that LAMBDA be the only special form.  Unless we
tackle the subject of macros in detail, I can't imagine subcategorizing
special forms into "real" special forms and "other" special forms, some of
which may be macros.

 -- I prefer named LET to ITERATE or RECURSE.  ITERATE is inadequate, while
RECURSE is poor English.  If we can't agree, lets make named LET and
perhaps one of the alternatives both optional (as Dan and Chris suggest).

 -- Let's drop LIST?.  It's both expensive and unimportant.  Make it
optional if you'd like.

 -- I like READ-CHAR-READY?.

 -- I don't like READ-READY?.  Its implementation would seem to require
buffering all of the characters going into a READ just in case we find they
don't add up to an entire parsable object.  HUNG? has the same problem.

 -- I agree that = and =? shouldn't both be essential.  I'm willing to
switch to the '?' forms if necessary, although I prefer the others for
compatibility with the Abelson and Sussman book and with Common Lisp.

 -- Let's drop #!NULL.  #!FALSE and () suffice.

 -- I'm willing to lose DEFINE! and DEFREC!, as Chris and Dan suggest.

 -- I favor retaining NUMBER?.

 -- OBJECT-HASH and OBJECT-UNHASH should be optional.

 -- I prefer REF over CELL (and CELL over BOX).  It should be optional.  In
our work, we are also concerned about locatives and forwarding pointers, so
it isn't clear to us that REF alone is interesting.

Regards,
David Bartley
-------


∂30-Mar-85  0047	@MIT-MC:CPH@MIT-OZ 	ITERATE, DEFINE and CELLs
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Mar 85  00:46:55 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 30 MAR 85  03:47:23 EST
Date: Sat, 30 Mar 1985  03:46 EST
Message-ID: <CPH.12099090096.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Chris Haynes <cth%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: ITERATE, DEFINE and CELLs
In-reply-to: Msg of 29 Mar 1985  08:49-EST from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    Date: Friday, 29 March 1985  08:49-EST
    From: Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    > 	How am I supposed to define things if both DEFINE! and DEFINE
    > go away?

    With SET!, provided one assumes that all identifiers are initially
    bound in the global environment, or that SET!  can extend the
    global environment.  With the exception of MIT's Scheme, this is
    what existing systems do.  If MIT is unwilling to change this,
    then we are reluctantly stuck with DEFINE.

This is a terrible idea.  It seems that the ability to have many
different environments in which to perform incremental definitions has
been consistently overlooked by almost everyone except MIT Scheme and
T.  Anyone who has ever tried to program a BIG system, and by that I
mean something over 500-1000 pages of code, knows that this kind of
packaging is **ESSENTIAL**!!  So please don't try to take this away.

∂30-Mar-85  0054	@MIT-MC:CPH@MIT-OZ 	The revised revised Report    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Mar 85  00:53:52 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 30 MAR 85  03:54:03 EST
Date: Sat, 30 Mar 1985  03:53 EST
Message-ID: <CPH.12099091315.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   David Bartley <Bartley%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: The revised revised Report
In-reply-to: Msg of 29 Mar 1985  15:37-EST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

Regarding your most recent set of (about 15) suggestions: I agree
completely with every single one of them.  Thank you.

∂31-Mar-85  1822	JAR@MIT-MC 	REC and LETREC    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Mar 85  18:22:26 PST
Date: 31 March 1985 21:22-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  REC and LETREC
To: JDR @ MIT-MC
cc: SCHEME @ MIT-MC

    Date: 29 Mar 1985 18:36:48-EST
    From: linus!ramsdell at Mitre-Bedford

    By the way, is the predicate PROCEDURE? missing?

It is intentionally missing; the decision to omit it was the outcome of
a discussion at the workshop.  As I remember, it was decided that it was
unnecessary, and certain people (me) thought it was possibly meaningless
and/or harmful.

    Could some one explain why LETREC is preferable to LABELS?

It was decided that a way to introduce local recursive definitions was
absolutely necessary; DEFINE of course being out of the question, there
was a heated debate between the names LABELS and LETREC, the LABELS
people arguing for English words and respect for the 1978 Revised Report
and Common Lisp, and the LETREC people arguing for something more
descriptive and allegedly pervasive in FP literature.  The LABELS camp
(me) was overwhelmed, so LETREC it is.  Let us be happy there was any
agreement at all.

Jonathan

∂31-Mar-85  1834	JAR@MIT-MC 	READ-CHAR-READY?  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Mar 85  18:34:31 PST
Date: 31 March 1985 21:34-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  READ-CHAR-READY?
To: SCHEME @ MIT-MC
In-reply-to: Msg of 29 Mar 1985 1437-CST from David Bartley <Bartley%ti-csl.csnet at csnet-relay.arpa>

I have a little trouble reading READ-CHAR-READY? ; it sounds like it
ought to be an imperative (read a ready character), until you get to
the question mark, and then it's hard to know what to think.  How about
something that sounds like it's asking a question?  Something like:
  WOULD-THE-READ-CHAR-PROCEDURE-BLOCK-IF-I-CALLED-IT?  only shorter.
How about INPUT-AVAILABLE?  or IMMEDIATELY-READABLE?  or
READABLE-WITHOUT-BLOCKING?  or something like that.  Does anyone else
like INPUT-AVAILABLE? ?  This is what it was always supposed to be
called in Yale Scheme, except that it never got implemented.

Jonathan

∂31-Mar-85  2042	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	REC and LETREC  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Mar 85  20:42:29 PST
Received: from csnet-relay by MIT-MC.ARPA; 31 MAR 85 23:42:10 EST
Received: from indiana by csnet-relay.csnet id ab16620; 31 Mar 85 23:28 EST
Date: Sun, 31 Mar 85 16:22:40 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA03507; Sun, 31 Mar 85 16:22:40 est
To: purdue!ihnp4!linus!ramsdell@mitre-bedf
Subject: REC and LETREC
Cc: scheme@mit-mc.ARPA

> linus!ramsdell@mitre-bedf / 11:41 pm  Mar 29, 1985 ****/
> 
> An English name for REC is PROCEDURE.  After all, that is
> what it returns.  By the way, is the predicate PROCEDURE?
> missing?

REC may not return a procedure, as in

(rec foo (cons exp (lambda () ...foo...))).

I think we agreed to omit PROCEDURE?, since it doesn't do much good to
know something is a procedure (without knowing how many args it wants,
whether it ever returns, etc.).

> Could some one explain why LETREC is preferable to LABELS?

LETREC is what it seems, a recursive variant of LET.  LABELS? only
expresses that it has something to do with naming (labeling) things.

Chris


∂31-Mar-85  2045	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	JINX reply on RECUR, DEFINE, ...    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Mar 85  20:44:53 PST
Received: from csnet-relay by MIT-MC.ARPA; 31 MAR 85 23:42:15 EST
Received: from indiana by csnet-relay.csnet id ac16620; 31 Mar 85 23:29 EST
Date: Sun, 31 Mar 85 20:07:15 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA02538; Sun, 31 Mar 85 20:07:15 est
To: scheme@mit-mc.ARPA
Subject: JINX reply on RECUR, DEFINE, ...

> Recursion for me (and most of the MIT-Scheme people) is a
> property of a process, not a feature of the particular syntax with
> which it was expressed.

We agree that the distinction between process and program is
fundamental.  But RECUR (Mitch's comment that RECURSE isn't English is
well taken) is at least expressive of the program (and has the
pedagogic virtue of emphasizing that program recursion expresses both
recursion and iteration of processes).  Local recursion (or iteration)
is too fundamental to be subsumed by LET, which expresses local
binding, *not* recursion (or iteration).  

We like Mitch's LABEL suggestion much better than named LET, but prefer
RECUR.

> SET! has too many connotations of side effects and I'm not willing
> to accept it as the primary definition mechanism.
> 
> I don't view definition as a side effect.  Its interactive
> implementation involves one, in the same way that the interpreted
> implementation of LETREC involve side effects, only because we don't
> know how to do it any better...
> 
> Purists in MIT-Scheme advocate for DEFINE to signal an error when
> attempting to redefine an already existing identifier in a given
> environment...

Your thorough justification of MIT's rationale is appreciated.  If
DEFINE could not be used to redefine existing bindings, we would have no
problem with it.  If the standard said that some systems may not permit
such redefinitions, we'd feel better about DEFINE being essential.
(Though most systems would allow redefinitions to ease reloading, as
you indicated.)

Your analogy with LETREC is not as close as you make it seem, for all
code within the scope of a LETREC is known at compile time, and the
same is not true for top level bindings.  (This is also the root of the
problem we have with the use of DEFINE as a substitute for LETREC.)
LETREC bindings are always new, never mutations of existing bindings.

> I'm willing to accept them in the standard as long as the CELL type
> is not required to be disjoint from PAIR (in the same way that
> CHARACTER is not required to be disjoint from STRING or INTEGER)...
> 
> If they are adopted I suggest the following names:
> 
> (MAKE-CELL VALUE) returns a CELL object with initial content VALUE.
> 
> (CELL-CONTENT CELL) returns the content of cell CELL.
> 
> (SET-CELL-CONTENT! CELL NEW-VALUE) makes the new content of CELL be
> NEW-VALUE.

We don't mind lack of disjointness.  The names you propose are better
than none at all, but not our favorites (here we go again...); we use
them a lot (sometimes more than explicit cons cells) and would like
shorter names.  BOX and REF have the advantage that UNBOX and DEREF
make sense, and SET-{CELL|BOX|REF}! is enough for mutation.  We don't
have to say CONS-CONTENT, or SET-CONS-CONTENT!.


We know everyone has had about enough of these name debates, but they have
served the useful purpose of clarifying our rationales.  We appreciate
Johnathan's restatement of the principle that if we can not agree after
making our rationales clear, then the standard should try to avoid
mentioning the points of contention.  This indicates that neither named
LET nor RECUR be mentioned.  DEFINE could stay, since that seems to be
the concensus, but it would be nice if its redefinition capability were
optional.

Chris
Dan


∂31-Mar-85  2047	@MIT-MC:cth%indiana.csnet@csnet-relay.arpa 	CPH reply on DEFINE  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Mar 85  20:47:28 PST
Received: from csnet-relay by MIT-MC.ARPA; 31 MAR 85 23:42:19 EST
Received: from indiana by csnet-relay.csnet id ad16620; 31 Mar 85 23:29 EST
Date: Sun, 31 Mar 85 20:08:00 est
From: Chris Haynes <cth%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA02544; Sun, 31 Mar 85 20:08:00 est
To: scheme@mit-mc.ARPA
Subject: CPH reply on DEFINE

> CPH%MIT-OZ@MIT-MC.ARPA /  9:33 am  Mar 30, 1985 ****/
> 
> It seems that the ability to have many
> different environments in which to perform incremental definitions has
> been consistently overlooked by almost everyone except MIT Scheme and
> T.  Anyone who has ever tried to program a BIG system, and by that I
> mean something over 500-1000 pages of code, knows that this kind of
> packaging is **ESSENTIAL**!!  So please don't try to take this away.

We grant the importance of such a facility, and are not trying to take it
way; but there is no concensus on how to provide such a facility, so it
is too soon to standardize on one.  (Similarly, syntactic extensions
are **ESSENTIAL** to the kind of thing we do here; but it is also too soon
to standardize on a syntactic extension mechanism.)

We were simply debating whether SET! should be required to extend the
global environment if its identifier is unbound (or equivalently, have
everything bound in the global environment to begin with).  This would
make DEFINE unessential, though it might still be optional.  It has
nothing to do with multiple environments for incremental definition,
except that MIT uses DEFINE for both purposes.

Chris
Dan


∂01-Apr-85  2047	JAR@MIT-MC 	CPH reply on DEFINE    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 1 Apr 85  20:47:02 PST
Date: 1 April 1985 23:46-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  CPH reply on DEFINE
To: cth%indiana.csnet @ CSNET-RELAY
cc: SCHEME @ MIT-MC
In-reply-to: Msg of Sun 31 Mar 85 20:08:00 est from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    Date: Sun, 31 Mar 85 20:08:00 est
    From: Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

    We were simply debating whether SET! should be required to extend the
    global environment if its identifier is unbound (or equivalently, have
    everything bound in the global environment to begin with).  This would
    make DEFINE unessential, though it might still be optional.  It has
    nothing to do with multiple environments for incremental definition,
    except that MIT uses DEFINE for both purposes.

I think that people at MIT and at Yale generally believe that SET!
should NOT cause the variable assigned to become bound in ANY
environment (global or otherwise) if it wasn't already.  Although MIT
Scheme's idea of environments argues for this position, there are these
other reasons: (1) taste - who wants to see all those side-effects all
over the place?; (2) one form one function - DEFINE binds, SET!
updates.

While I appreciate your desire to simplify things, DEFINE and SET! are
viewed here as two totally different operations, so I think they should
remain separate & required, as we agreed last fall.

Jonathan

∂02-Apr-85  0005	@MIT-MC:CPH@MIT-OZ 	CPH reply on DEFINE 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 2 Apr 85  00:05:44 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 2 APR 85  03:05:44 EST
Date: Tue, 2 Apr 1985  03:05 EST
Message-ID: <CPH.12099869022.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Chris Haynes <cth%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: CPH reply on DEFINE
In-reply-to: Msg of 31 Mar 1985  20:08-EST from Chris Haynes <cth%indiana.csnet at csnet-relay.arpa>

My apologies for the rather careless wording of my earlier message.

What I wanted to say was: if SET! extends the "global" environment,
then that environment has become special in that it is the ONLY
environment that can be extended by interactive definition.  This
would seem to preclude the existence of many such environments.

DEFINE eliminates the problem, because it specifies, very precisely,
the environment in which the name is bound.

∂09-Apr-85  0637	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	First Class Environments and Their Extenders
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Apr 85  06:36:58 PST
Received: from csnet-relay by MIT-MC.ARPA;  9 APR 85 09:37:06 EST
Received: from indiana by csnet-relay.csnet id a001256; 9 Apr 85 9:36 EST
Date: Tue, 9 Apr 85 02:35:36 est
From: Perry Wagle <wagle%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA15319; Tue, 9 Apr 85 02:35:36 est
To: scheme%indiana.csnet@csnet-relay.arpa
Subject: First Class Environments and Their Extenders

  My ATN (Augmented Transition Network) is a macro that makes a grammar into
an object.  This object (currently) is a closure taking one argument that is
evaluated in an environment where each state has been transformed into a
function of (currently) five arguments using letrec.  Roughly:

	(define-atn my-atn state2 (state1 arc1 arc2) (state2 arc3 arc4))

is transformed to:

	(letrec ((state1 (lambda (...) (nexus arc1 arc2)))
		 (state2 (lambda (...) (nexus arc3 arc4))) )
	  (define! my-atn
	    (lambda (*sentence*) (state2 ...))))

where the "..." means "fill in the blank".  NEXUS is a macro that determines
the evaluation order of the arcs (depth-first, breadth-first, parallel, etc).

  One problem with this is that if I have a large ATN (with say 100 states,
and an average branching factor of 5), the compile can take a significant
amount of time, even if I have a VAX 780 all to myself at 3AM.

  How do you debug the grammar.  Well, first you find the state in which it
failed, you modify the source code of the grammar, and then you recompile
the ENTIRE GRAMMAR.  Yuck!

  The standard solution to this in the literature of ATNs (and AI in
general) seems to be to define each state as a global-binding, and not to
worry about trying to package them all up in objects.  I don't like this
because its not modular -- the inards of each compiled atn-grammar is
sprawled out everywhere.  I have several different atn-grammars, and I
don't want to worry about them interfering with one another.

  The letrec method is a nice method, and I would like to make it work.

  My current view of what I think I want is this:  That letrec in the
right-hand-side of the transformation at the beginning of this note defined
a new rib (MY←RIB) in front of the "current" environment (OLDENV) creating a
new environment (MY←ENV).  I want to rebind variables in MY←RIB to
expressions EVALuated in MY←ENV, and I want to extend MY←RIB with new
variables bound to the evaluations of expressions EVALuated in MY←ENV (with
MY←ENV already extended by the new variable (which is initially bound to
something like '#!unspecified', then rebound to the new value -- that is,
normal letrec semantics).  I could then create functions (macros?) like
'editstate', 'addstate', 'trace-state', 'untrace-state', etc.  that would do
the obvious things to a particular compiled-atn-grammar.  This way, I only
have to recompile the state, not the entire grammar.

  Put another way, I can modify the grammar interactively rather than in
batch mode like I am now.

PS -- I designed it this way, because I heard that first class environments
were on their way, and I thought it would eventually work the way I wanted
it too.  But apparently now, the idea is that you should ONLY be able to
extend the LAST rib in the rib sequence.  Seeing as how I want to extend the
second to the last rib (and two is an arbitrary number), and there being a
number of programming technique reasons for putting new ribs between me and
the second to the last rib, I have to object and call for a facility
something like 'call-with-current-rib-set!' (where set! is rebind
and extend as one), and I need to EVAL (compile, execute) in the proper
environment, MY←ENV, which is not necessarily equal to the current one, and
is procured with something like 'call-with-current-environment'.

  'call/c←rib' is not necessarily incompatable with 'call/c←env' (as I almost
thought) as I can:

	(let ((MY←RIB (call/c←rib (lambda (x) x)))
	      (MY←ENV (call/c←env (lambda (x) x))) )
	  (some function of MY←RIB and MY←ENV here) )

  As long as I can grab a rib extender, and EVAL in a environment other than
the current one, everything is fine.  The call/c←rib and call/c←env is just
illustration.

  As I think that this generalizes to objects (modules), I don't think calls
to rewrite my ATN are in order unless they make the same generalization.


∂10-Apr-85  0107	@MIT-MC:CPH@MIT-OZ 	First Class Environments and Their Extenders 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 10 Apr 85  01:06:32 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 10 APR 85  04:06:27 EST
Date: Wed, 10 Apr 1985  04:07 EST
Message-ID: <CPH.12101977358.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Perry Wagle <wagle%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC
Subject: First Class Environments and Their Extenders
In-reply-to: Msg of 9 Apr 1985  02:35-EST from Perry Wagle <wagle%indiana.csnet at csnet-relay.arpa>

Why did your message get sent to this mailing list?  I think that
there must have been some mistake as it seems to be inappropriate to
the purpose of the mailing list, which is a forum for the Scheme
report proposal.

∂21-Apr-85  0652	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	if, mapcar, mapc, ...   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  06:51:52 PST
Received: from csnet-relay by MIT-MC.ARPA; 21 APR 85 09:52:11 EST
Received: from indiana by csnet-relay.csnet id a026012; 21 Apr 85 9:54 EST
Date: Sat, 20 Apr 85 15:28:35 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA04262; Sat, 20 Apr 85 15:28:35 est
To: scheme@mit-mc.ARPA
Subject: if, mapcar, mapc, ...

This note proposes a few significant changes and corrections to
the draft of the "Revised Revised Report".  Let me know if I have
misread the consensus.

I am moving to Oregon in two weeks.  I expect June will arrive
before I have finished typesetting this thing.

				William Clinger

----------------------------------------------------------------

Following the Algol 60 report, I propose that all attendees at
the Brandeis workshop be listed as authors.  The acknowledgements
will list other participants in the discussion over the network,
and I will sign an editor's note accepting blame for errors in
transcription and interpretation.

Chris Hanson's revised report on strings will be incorporated.

In resonse to a few complaints, I would like to replace the last
paragraph in Section I.0 ("Brief history of Scheme") with:

    Scheme shares with Common Lisp [\ref] the goal of a core
    language common to several implementations.  Scheme differs
    from Common Lisp in its emphasis upon simplicity and
    function over compatibility with older dialects of Lisp.

To allow for less error checking in compiled code, in the
discussion of variable references in section II.1 "An error is
signalled if {\it variable} is unbound" should read "It is an
error if {\it variable} is unbound".

Two-armed if will change from essential to optional status.

In the discussion of cond, "The special keyword {\tt else} may be
used..." should read "The keyword or variable {\tt else} may be
used...".

define! and defrec! will be flushed altogether.

The rationale for set! will be flushed.

In the header line for backquote, "macro special form" should be
"special form".

The initial value for nil (if it is provided at all) should be
#!null rather than #!false.

Several people have asked that append! not be allowed to side
effect its last argument, so unless there is opposition that
change will be made.

See my separate note for the proposed lexical syntax of numbers
and some questions that I have concerning numbers.

There is a problem with object-hash and object-unhash.  People
might want to ask themselves whether object-unhash is really useful.
The following scenario will be added to the rationale:

	>>>(define x (cons 0 0))
	x
	>>>(object-hash x)
	77
	>>>(set! x 0)
	...
	>>>(gc)		; garbage collection occurs for some reason
	...
	>>>(object-unhash 77)
	???		; ill-defined: #!false or (0 . 0)

The name of mapcar will be changed to map.  (There seems to be a
fair consensus for this.)

The name of mapc will be changed to for-each.  (There seems to be
a fair consensus that it should be changed, and for-each seems to
me to be the best name that has been proposed.  At any rate it is
the only name that has been proposed that has not drawn
objections.)

call-with-current-continuation is essential.  That it was not so
indicated in the draft was a gross blunder.

The introductory material for call-with-current-continuation will
be moved to the rationale.  The last sentence of the rationale,
which begins "Some people think...", will be changed to read
"Although the name is descriptive, some people feel it is too
long and have taken to calling the procedure call/cc".

The original explanation of call-with-input-file and
call-with-output-file allows the port to be closed on any throw.
This makes it impossible to use escape procedures in a portable
manner.  The sentence beginning "If the current continuation ever
changes in such a way as to make it doubtful that the procedure
will return..." will therefore change to "The implementation must
not close the port unless it can prove that the port will never
again be used for a read or write operation."

eof? will be renamed eof-object?

listen? will be renamed char-ready?.  (Everyone agreed that the
name should be changed, but there was little agreement on the new
name.  No one seemed to care very much either.)  It will be
required that if char-ready? returns #!true, then the next
read-char operation on the port must not hang, and it will be
pointed out that this has implications for the way that rubout
handlers are written.

It will be required that the load procedure does not affect the
values returned by current-input-port and current-output-port.

There are many small improvements and corrections to be made
also, but I won't bore you with them.  (The above should
suffice.)


∂21-Apr-85  0654	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	lexical syntax for numbers   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  06:54:22 PST
Received: from csnet-relay by MIT-MC.ARPA; 21 APR 85 09:52:17 EST
Received: from indiana by csnet-relay.csnet id aa26012; 21 Apr 85 9:54 EST
Date: Sat, 20 Apr 85 15:33:46 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA04306; Sat, 20 Apr 85 15:33:46 est
To: scheme@mit-mc.ARPA
Subject: lexical syntax for numbers

A proposed lexical syntax for Scheme numbers.


The draft of the Revised Revised Report did not specify a lexical
syntax for numbers.  This proposal is consistent with the draft
but it incorporates a large number of rather arbitrary decisions
that are likely to be controversial.  Feel free to controverse.

Actually there are two proposals.  The first proposal is for full
(optional) Scheme and the second is for essential Scheme.
(Implementations would be free to implement anything in between
or to extend the syntax so long as the extended syntax didn't
conflict with the optional syntax, right?)

x* means zero or more occurrences of x.
Spaces never appear inside a number, so all spaces in the syntax
are for legibility.
<empty> is the empty string.


bit -->  0  |  1

oct -->  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7

dit -->  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9

hit -->  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9
      |  a  |  b  |  c  |  d  |  e  |  f  
      |  A  |  B  |  C  |  D  |  E  |  F

radix2  -->  #b  |  #B

radix8  -->  #o  |  #O

radix10  -->  <empty>  |  #d  |  #D

radix16  -->  #h  |  #H

exactness  -->  <empty>  |  #i  |  #I  |  #e  |  #E

precision  -->  <empty>  |  #s  |  #S  |  #l  |  #L

prefix2  -->  radix2 exactness precision  |  radix2 precision exactness
           |  exactness radix2 precision  |  exactness precision radix2
	   |  precision radix2 exactness  |  precision exactness radix2

prefix8  -->  radix8 exactness precision  |  radix8 precision exactness
           |  exactness radix8 precision  |  exactness precision radix8
	   |  precision radix8 exactness  |  precision exactness radix8

prefix10  -->  radix10 exactness precision  |  radix10 precision exactness
            |  exactness radix10 precision  |  exactness precision radix10
	    |  precision radix10 exactness  |  precision exactness radix10

prefix16  -->  radix16 exactness precision  |  radix16 precision exactness
            |  exactness radix16 precision  |  exactness precision radix16
	    |  precision radix16 exactness  |  precision exactness radix16

sign  -->  <empty>  |  +  |  -

suffix  -->  <empty>  |  e d d*  |  E d d*  |  e - d d*  |  E - d d*

ureal  -->  prefix2 bit bit* #* suffix
	 |  prefix2 bit bit* #* / bit bit* #* suffix
         |  prefix2 . bit bit* #* suffix
	 |  prefix2 bit bit* . bit* #* suffix
	 |  prefix2 bit bit* #* . #* suffix

         |  prefix8 oct oct* #* suffix
	 |  prefix8 oct oct* #* / oct oct* #* suffix
         |  prefix8 . oct oct* #* suffix
	 |  prefix8 oct oct* . oct* #* suffix
	 |  prefix8 oct oct* #* . #* suffix

         |  prefix10 dit dit* #* suffix
	 |  prefix10 dit dit* #* / dit dit* #* suffix
         |  prefix10 . dit dit* #* suffix
	 |  prefix10 dit dit* . dit* #* suffix
	 |  prefix10 dit dit* #* . #* suffix

         |  prefix16 hit hit* #* suffix
	 |  prefix16 hit hit* #* / hit hit* #* suffix
         |  prefix16 . hit hit* #* suffix
	 |  prefix16 hit hit* . hit* #* suffix
	 |  prefix16 hit hit* #* . #* suffix

real  -->  sign ureal

number  -->  real  |  real + ureal i  |  real - ureal i  |  real @ real


Some consequences of this syntax are reported below.  Please keep
in mind that when I say a syntax is "illegal", I mean that it is
not generated by the syntax above and is therefore not a number
in (full optional) Scheme.  The syntax could represent a legal
symbol or even a legal number in an extended Scheme.

Consequences:

Exponents are always in base 10.
Exponents may not have explicit + signs.

	e+4			is illegal
	1E+3			is illegal
	#d+3 			is illegal
	4-+5i			is illegal
	4#.5			is illegal
	#d5/#o10		is illegal
	-4/-5			is illegal
	#o5/10			is .625
	#s4			is legal
	#s#i#b.10##-#x#L#Ea.bi	is legal



The proposal for essential Scheme:


dit -->  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9

sign  -->  <empty>  |  +  |  -

number  -->  sign dit dit*




Question about exactness:  In an implementation that doesn't keep
track of exactness, the exact? predicate should always return
#!false.  Right?

				William Clinger
				willc@indiana
	after 1 May:		willc@tektronix


∂21-Apr-85  1444	@MIT-MC:rhh@MIT-VAX 	reactions to Will's updates  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  14:44:02 PST
Received: from MIT-VAX by MIT-MC via Chaosnet; 21 APR 85  17:44:14 EST
Received: by mit-vax.Mit-chaos.Arpa (4.12/4.8) id AA03260; Sun, 21 Apr 85 17:43:51 est
Date: Sun, 21 Apr 85 17:43:51 est
From: Bert Halstead <rhh@mit-vax>
To: scheme@mc
Subject: reactions to Will's updates

unhash-object sounds like a bad idea.  In Will's scenario, if an object
(0 . 0) is passed to hash-object, and, say, 77 is returned, subsequent
calls to (unhash-object 77) must return either (0 . 0) or #!false
(presumably the latter is an out if the (0 . 0) has been garbage-
collected).  This implies that 77 can NEVER be reused as the hash
code for some other object passed to hash-object!  It also implies
(do we want this?) that hash-object is a one-to-one function -- it
is never permissible for more than one object to map to the same hash
code.  This is not necessary if hash-object is just a way to compute
an index into some user-maintained hash table, where objects could
be associated with whatever information is desired.

re numbers:  Is anything substantial gained by disallowing explicit
"+" signs on the exponents of numbers in scientific notation?  -Bert

∂21-Apr-85  1923	@MIT-MC:JINX@MIT-OZ 	lexical syntax for numbers   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  19:22:56 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 21 APR 85  22:22:06 EST
Date: 21 Apr 1985  22:20 EST (Sun)
Message-ID: <JINX.12105060042.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Will Clinger <willc%indiana.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: lexical syntax for numbers
In-reply-to: Msg of 20 Apr 1985  15:33-EST from Will Clinger <willc%indiana.csnet at csnet-relay.arpa>

Two comments:

Why can't exponents have + signs, and why must they be decimal?  It
seems to me that they should be any valid representation of an
integer, though they may always want to be exact.

Why don't we fix the order of the exactness, radix, and precision
modifiers?  I don't think anything is gained from allowing arbitrary
order and the parser may become simpler if it can easily default.

∂21-Apr-85  1927	@MIT-MC:JINX@MIT-OZ 	reactions to Will's updates  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  19:27:08 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 21 APR 85  22:25:23 EST
Date: 21 Apr 1985  22:24 EST (Sun)
Message-ID: <JINX.12105060636.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Bert Halstead <rhh%MIT-VAX@MIT-MC.ARPA>
Cc:   scheme@MIT-MC
Subject: reactions to Will's updates
In-reply-to: Msg of 21 Apr 1985  17:43-EST from Bert Halstead <rhh at mit-vax>

Instead of hash-object and unhash-object, why don't we include
populations?  The implementation can be done in terms of hash and
unhash object or more primitively, and they seem to constitute the
most common use of these procedures.

∂21-Apr-85  1929	@MIT-MC:CPH@MIT-OZ 	lexical syntax for numbers    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  19:29:47 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 21 APR 85  22:29:25 EST
Date: Sun, 21 Apr 1985  22:28 EST
Message-ID: <CPH.12105061355.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Cc:   Scheme@MIT-MC.ARPA
Subject: lexical syntax for numbers
In-reply-to: Msg of 21 Apr 1985  22:20-EST from Bill Rozas <JINX>

    Date: Sunday, 21 April 1985  22:20-EST
    From: Bill Rozas <JINX>

    Why don't we fix the order of the exactness, radix, and precision
    modifiers?  I don't think anything is gained from allowing arbitrary
    order and the parser may become simpler if it can easily default.

One thing that is gained from arbitrary order is that one need not
remember what the particular order is -- a great advantage to people
who don't remember trivial details very well and don't like reading
manuals.

∂21-Apr-85  1931	@MIT-MC:CPH@MIT-OZ 	reactions to Will's updates   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Apr 85  19:31:29 PST
Received: from MIT-OZ by MIT-MC via Chaosnet; 21 APR 85  22:31:16 EST
Date: Sun, 21 Apr 1985  22:29 EST
Message-ID: <CPH.12105061716.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Cc:   Bert Halstead <rhh%MIT-VAX@MIT-MC.ARPA>, scheme@MIT-MC
Subject: reactions to Will's updates
In-reply-to: Msg of 21 Apr 1985  22:24-EST from Bill Rozas <JINX>

    Date: Sunday, 21 April 1985  22:24-EST
    From: Bill Rozas <JINX>

    Instead of hash-object and unhash-object, why don't we include
    populations?  The implementation can be done in terms of hash and
    unhash object or more primitively, and they seem to constitute the
    most common use of these procedures.

Actually, the major reason that we implemented hashing is to have
generalized two dimensional property tables, for generic operations.

∂22-Apr-85  1103	JAR@MIT-MC 	hashing 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  11:03:43 PST
Date: Mon, 22 Apr 85 13:40:27 EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  hashing
To: rhh@MIT-VAX
cc: SCHEME@MIT-MC
In-reply-to: Msg of Sun 21 Apr 85 17:43:51 est from Bert Halstead <rhh at mit-vax>
Message-ID: <[MIT-MC].464776.850422.JAR>

    Date: Sun, 21 Apr 85 17:43:51 est
    From: Bert Halstead <rhh at mit-vax>

    ...  This implies that 77 can NEVER be reused as the hash
    code for some other object passed to hash-object!

This is an intentional feature of the proposal; if recycling is
permitted then the facility takes on a totally different character and
has more liimted application.

Feature:

Non-re-use means that OBJECT-UNHASH, which is desirable for many
applications of these things (like post-GC automatic file closing, weak
tables, and populations), is possible and meaningful.

Antifeatures:

(1) Non-re-use means that OBJECT-HASH is different from Maclisp MAKNUM,
and is therefore, presumably, more expensive.

(2) Non-re-use means that in very-long-lived systems, hash numbers might
go into bignums.

---

The hash/unhash facility is already optional, and I would suggest that
if for some reason you don't like its details you can just not implement
it.

If there is much disagreement now about the facility, then it should be
removed from the report.  This removal should be done carefully, since
we agreed on it last fall, and agreements are precious; a different hash
facility probably won't make it into the report.

Jonathan

∂22-Apr-85  1117	JAR@MIT-MC 	hashing 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  11:17:40 PST
Date: Mon, 22 Apr 85 14:12:52 EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  hashing
To: JINX@MIT-OZ
cc: SCHEME@MIT-MC, rhh@MIT-VAX
In-reply-to: Msg of 21 Apr 1985  22:24 EST (Sun) from Bill Rozas <JINX%MIT-OZ at MIT-MC.ARPA>
Message-ID: <[MIT-MC].464817.850422.JAR>

    Date: 21 Apr 1985  22:24 EST (Sun)
    From: Bill Rozas <JINX%MIT-OZ at MIT-MC.ARPA>

    Instead of hash-object and unhash-object, why don't we include
    populations?  The implementation can be done in terms of hash and
    unhash object or more primitively, and they seem to constitute the
    most common use of these procedures.

I don't think populations are much easier to implement than hash/unhash,
and they aren't as general.  T started out having populations, and a
year or two later acquired OBJECT-HASH, which was applicable in many
situations where populations wouldn't do.  (I think you might be able
to implement hash/unhash in terms of populations, but it's much less
natural than vice versa.)

Uses for hash/unhash include populations, weak tables, and file closing,
as well as the following interesting hack, which has tremendous
popularity with users:  PRINT calls OBJECT-HASH when it comes across an
object with no standard external representation, a procedure for
example, and prints the hash number along with any other type and
identification info it can find: e.g.

    > cadr				;User's typein
    #{Procedure 31 CADR}		;System's typeout
    > (lambda (x) (* x 3))
    #{Procedure 32}
    > 

Although the syntax #{...} isn't readable (that could cause very bizarre
results for READ's done in processes different from the one which
printed the object), you can evaluate (OBJECT-UNHASH 32) and, if the
garbage collector hasn't done away with it, get the procedure back.
This is vaguely like "D-lines" in Macsyma, except that it permits
reclamation.

Note that hash is called only when PRINT is called, so there is no
evaluator overhead involved.  (One user was at first baffled by the
following interaction:

    > (lambda () 1)
    #{Procedure 33}
    > (lambda () 2)
    #{Procedure 34}
    > (do ((i 0 (1+ i))
	   (p nil (lambda () i)))
	  ((= i 100) p))
    #{Procedure 35}
    > 

and then figured out that PRINT was generating the numbers.)

∂22-Apr-85  1226	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	mapcar and mapc    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  12:25:45 PST
Received: from csnet-relay by MIT-MC.ARPA; 22 APR 85 15:24:22 EST
Received: from indiana by csnet-relay.csnet id a002853; 22 Apr 85 15:16 EST
Date: Mon, 22 Apr 85 13:54:19 est
From: Perry Wagle <wagle%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA17597; Mon, 22 Apr 85 13:54:19 est
To: scheme%indiana.csnet@csnet-relay.arpa
Subject: mapcar and mapc

  In response to Will Clinger's acceptance of the "mapc" -> "for-each"
renaming:

  How about renaming "mapc" to "mapcar!" (and thence to "map!")?

  This would change the meaning of the bang notation from "Hi! I'm a
side-effecting function" to "Hi! I'm expecting either myself or one of the
functions that I call to be a side-effecting function".

  This way, the two very simular functions "map" and "map!" keep simular
names, making life easier on the frail memory of the user.

						Perry Wagle


∂22-Apr-85  1302	@MIT-MC:rhh@MIT-VAX 	Re:  hashing  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  13:02:29 PST
Received: from MIT-VAX by MIT-MC via Chaosnet; 22 APR 85  16:02:23 EST
Received: by mit-vax.Mit-chaos.Arpa (4.12/4.8) id AA08654; Mon, 22 Apr 85 16:02:07 est
Date: Mon, 22 Apr 85 16:02:07 est
From: Bert Halstead <rhh@mit-vax>
To: JAR@MIT-MC
Subject: Re:  hashing
Cc: SCHEME@MIT-MC

Roger, I'm sensitive to the practical issues you raise, as to the mechanics
of getting agreement on the Scheme report.  I don't object to object-hash
and object-unhash as optional Scheme functions -- I was just flaming about
implementation considerations which, if they had occurred to me during the
workshop, I had long since forgotten about.  It does seem like the issues
of long-lived systems, and the cost of maintaining a hash space that is
ultimately sparsely populated, provide some food for thought.  But that's
one thing that optional features are for.		-b.

∂22-Apr-85  1544	@MIT-MC:linus!ramsdell@mitre-bedford 	Two armed IF is essential. 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  15:44:28 PST
Received: from mitre-bedford by MIT-MC.ARPA; 22 APR 85 18:43:53 EST
Date: 22 Apr 1985 18:36:48-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA11664; Mon, 22 Apr 85 09:57:17 est
Date: Mon, 22 Apr 85 09:57:17 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8504221457.AA11664@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: Two armed IF is essential.

>>>From bccvax!willc%indiana.csnet@csnet-relay.arpa Sun Apr 21 14:30:50 1985
>>>...
>>>Two-armed if will change from essential to optional status.

One-armed IF may change from essential to optional status,
but please don't change two-armed IF.
John

∂22-Apr-85  1547	@MIT-MC:linus!ramsdell@mitre-bedford 	REC => LABEL
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Apr 85  15:46:59 PST
Received: from mitre-bedford by MIT-MC.ARPA; 22 APR 85 18:44:29 EST
Date: 22 Apr 1985 18:36:55-EST
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA12343; Mon, 22 Apr 85 10:34:00 est
Date: Mon, 22 Apr 85 10:34:00 est
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8504221534.AA12343@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: REC => LABEL

I know its too late, but I support Mitch Wand's
suggested rename for REC.
John

∂23-Apr-85  0912	@MIT-MC:wagle%indiana.csnet@csnet-relay.arpa 	Retraction and Resubmission  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Apr 85  09:11:58 PST
Received: from csnet-relay by MIT-MC.ARPA; 23 APR 85 11:58:20 EST
Received: from indiana by csnet-relay.csnet id ad08662; 23 Apr 85 11:52 EST
Date: Tue, 23 Apr 85 11:12:36 est
From: Perry Wagle <wagle%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA11641; Tue, 23 Apr 85 11:12:36 est
To: scheme%indiana.csnet@csnet-relay.arpa
Subject: Retraction and Resubmission

  I noticed later that my suggestion about the renaming of "mapc" is
somewhat bogus, I apologize:

  Mapcar-type functions have two primary operating parameters: (1) the order
in which the list is processed, (2) a resultant value from whether the list
is copied, side-effected, or forgotten.

  The current "mapcar" processes in arbitrary order and returns the copied
list.  The current "mapc" processes in left-to-right order and forgets the
list (returning nothing).  Quite, ahem, different.

  (The most direct interpretation of a function named "mapcar!" would be one
that set-car!ed the list, returned the side-effected list, and was open as
to whether to process in arbitrary or left-to-right order.)


  I would have use for (in order of frequency):

(1)  arb-order, copy list, return list.  (the current mapcar).
(2)  LR-order, copy list, return list.  I don't like set-car!ing cons-cells,
     but I make much use of files and continuations, so order matters a lot.
(3)  LR-order, forget list, return nothing. (the current mapc).  Print lists.
(4)  LR-order, side-effect list, return list.  If keeping same cons-cell is
     important for some reason.

  Perhaps only a subset of the set of useful mapcar variations should be
provided by the system - the two that already are?  The points would still
remain of denoting their status as a member of this grouping by using the
word "map" in the name, of having special marking for functions that
guarantee left-to-right evaluation or processing, and having a naming
convention for the others should they ever be realized.

  My suggestion is to distinguish between the arbitrary and left-to-right
list processing but starting off with two roots "map" and "map/lr",
respectively.  Futhermore, since there are three values returned - a copied
list, a set-car!ed list, and nothing at all - "copy", "list!", and "" (null),
respectively.  Then the four hypothetical functions above would be named:

(1)	"map->copy"
(2)	"map/lr->copy"
(3)	"map/lr"
(4)	"map/lr->list!" or "map/lr->same!" or ... (?)

  (Note that while there would be no reasonable value for (a fifth) "map" to
return, while "map/lr" could return the value of the last mapping.)

						Perry Wagle


∂23-Apr-85  1336	JAR@MIT-MC 	Two armed IF is essential.  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Apr 85  13:36:20 PST
Date: Tue, 23 Apr 85 16:25:21 EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  Two armed IF is essential.
To: SCHEME@MIT-MC, linus!ramsdell@MITRE-BEDFORD
In-reply-to: Msg of 22 Apr 1985 18:36:48-EST
      Mon 22 Apr 85 09:57:17 est from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford
Message-ID: <[MIT-MC].466615.850423.JAR>

    Date: 22 Apr 1985 18:36:48-EST
    From: linus!ramsdell at Mitre-Bedford

    One-armed IF may change from essential to optional status,
    but please don't change two-armed IF.

I think this was what Will intended to write.  The terminology is
confusing, since an IF with N arms has N+1 subforms, and he probably
wrote arm and meant subform.

So:  (IF test consequent alternate)  essential
     (IF test consequent)	     optional

Jonathan

∂24-Apr-85  1541	@MIT-MC:willc%indiana.csnet@csnet-relay.arpa 	two-armed if (oops)
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Apr 85  15:41:40 PST
Received: from csnet-relay by MIT-MC.ARPA; 24 APR 85 18:41:59 EST
Received: from indiana by csnet-relay.csnet id ad16863; 24 Apr 85 14:38 EST
Date: Wed, 24 Apr 85 12:48:17 est
From: Will Clinger <willc%indiana.csnet@csnet-relay.arpa>
Received: by iuvax.UUCP; id AA05047; Wed, 24 Apr 85 12:48:17 est
To: scheme@mit-mc.ARPA
Subject: two-armed if (oops)

Yikes!  Thank you John, I meant to say that ONE-ARMED IF would become
optional.  TWO-ARMED IF will remain essential, of course.

There has already been sufficient response to convince me that plus signs
should be allowed in exponents.

Still at issue is whether exponents can have radix, precision, or exactness
specifiers, and indeed whether exponents should be allowed to have arbitrary
number syntax.  At some point the more general exponent syntax should become
extended rather than optional, and all we're trying to do is to determine
that point.
				Peace, William


∂25-Apr-85  0902	@MIT-MC:rhh@MIT-VAX 	number exponent syntax  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Apr 85  09:01:49 PST
Received: from MIT-VAX by MIT-MC via Chaosnet; 25 APR 85  12:03:03 EST
Received: by mit-vax.Mit-chaos.Arpa (4.12/4.8) id AA05298; Thu, 25 Apr 85 12:01:58 est
Date: Thu, 25 Apr 85 12:01:58 est
From: Bert Halstead <rhh@mit-vax>
To: scheme@mit-mc.ARPA, willc%indiana.csnet@csnet-relay.arpa
Subject: number exponent syntax

Seems to me that precision and exactness are (almost) completely
meaningless in an exponent.  One could perhaps make an argument for
different radices in the exponent notation, but then one could also
make an argument for other things (e.g., scientific notation with
a base other than 10).  I'd probably just as soon we didn't.  -Bert

∂26-Apr-85  0037	JAR@MIT-MC 	number exponent syntax 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Apr 85  00:36:50 PST
Date: Thu, 25 Apr 85 15:42:31 EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  number exponent syntax
To: rhh@MIT-VAX
cc: SCHEME@MIT-MC
In-reply-to: Msg of Thu 25 Apr 85 12:01:58 est from Bert Halstead <rhh at mit-vax>
Message-ID: <[MIT-MC].469882.850425.JAR>

    Date: Thu, 25 Apr 85 12:01:58 est
    From: Bert Halstead <rhh at mit-vax>

    Seems to me that precision and exactness are (almost) completely
    meaningless in an exponent.  One could perhaps make an argument for
    different radices in the exponent notation, but then one could also
    make an argument for other things (e.g., scientific notation with
    a base other than 10).  I'd probably just as soon we didn't.

I'm not one to talk, since I never use numbers, but I read a CACM
article once about a proposed hardware number representation in which
one could represent numbers with no significant digits in their
EXPONENT.  The author claimed that this was useful.  So not all of
this meaninglessness is to be concluded forgonely.

Don't take this as a contrary argument; merely a word of caution.

Jonathan

∂26-Apr-85  0351	@MIT-MC:rhh@MIT-VAX 	Re:  number exponent syntax  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Apr 85  03:51:03 PST
Received: from MIT-VAX by MIT-MC via Chaosnet; 25 APR 85  16:08:56 EST
Received: by mit-vax.Mit-chaos.Arpa (4.12/4.8) id AA09287; Thu, 25 Apr 85 16:07:44 est
Date: Thu, 25 Apr 85 16:07:44 est
From: Bert Halstead <rhh@mit-vax>
To: JAR@MIT-MC
Subject: Re:  number exponent syntax
Cc: SCHEME@mc

Yeah, I saw the same article, and it was the thought of that that caused
me to insert the words "(almost)" in my message.  But once we start
having impreciseness in our exponent, there is little point to saying
anything about the mantissa!  I figured this was probably a minefield
Scheme could avoid entering.					-Bert

∂21-Jun-85  1631	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@csnet-relay.arpa 	lcm
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Jun 85  16:31:10 PDT
Received: from csnet-relay by MIT-MC.ARPA 21 Jun 85 19:31:11 EST
Received: from tektronix by csnet-relay.csnet id ac01342; 21 Jun 85 18:43 EDT
From: Will Clinger <willc%tekchips%tektronix.csnet@csnet-relay.arpa>
To: scheme@MIT-MC.ARPA
Received: from tekchips by tektronix with smtp ; 21 Jun 85 11:30:56 PDT
Date: Friday, 21 Jun 85 11:25:37 PDT
Subject: lcm

A question from John Gateley (gateley%waltz@ti-csl.csnet) and my response:

Gateley:

   Common lisp says (lcm) = infinity, and since they don't have
   a representation of infinity, lcm is required to have at least
   one argument. Scheme says (lcm) = 1.  Also, common lisp allows lcm to
   take 0 as an argument, with result 0. Scheme does not allow zero as
   an argument. Is this what is desired, or should scheme be closer to
   common lisp.

Clinger:

The relevant passage in Guy Steele's book is on page 202:

    "Mathematically, (lcm) should return infinity.  Because Common Lisp
    does not have a representation for infinity, lcm, unlike gcd, always
    requires at least one argument."

Even as a mathematician, I can't agree that (lcm) should return infinity,
because the n-ary generalization of an associative binary operator should
return an identity for the operator when it is given no arguments.  Infinity
certainly isn't an identity for lcm.  1 is.

I think I inserted the requirement that the arguments to lcm be non-zero.  I
have no particular quarrel with Common Lisp on this matter, but I didn't want
to get bogged down in pathological cases.  Since it is inconsistent to allow
zero as an argument to gcd but not to lcm, I would like to change the report so
that lcm behaves as in Common Lisp when given a zero argument.


∂21-Jun-85  1723	@MIT-MC.ARPA:ANDY@SU-SUSHI.ARPA 	Re: lcm
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Jun 85  17:23:16 PDT
Received: from SU-SUSHI.ARPA by MIT-MC.ARPA 21 Jun 85 20:22:54 EST
Date: Fri 21 Jun 85 17:22:22-PDT
From: Andy Freeman <ANDY@SU-SUSHI.ARPA>
Subject: Re: lcm
To: willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA
cc: scheme@MIT-MC.ARPA
In-Reply-To: Message from "Will Clinger <willc%tekchips%tektronix.csnet@csnet-relay.arpa>" of Fri 21 Jun 85 16:37:59-PDT

(lcm) recently came up on the common lisp mailing list and that the
decision was that the Common Lisp manual was wrong.  I believe Bill
Gosper and Alan Bawden were major participants in that discussion.
I'd review that before making a decision.

-andy
-------

∂09-Jul-85  2145	@MIT-MC.ARPA:ALTMAN%ti-csl.csnet@csnet-relay.arpa 	Scheme Benchmark Programs Sought  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Jul 85  21:45:03 PDT
Received: from csnet-relay by MIT-MC.ARPA.ARPA; 10 Jul 85 00:39:55 EDT
Received: from ti-csl by csnet-relay.csnet id aj16083; 10 Jul 85 0:30 EDT
Date:  9 Jul 1985 0937-CDT
From: Arthur <Altman%CSL60%ti-csl.csnet@csnet-relay.arpa>
Subject: Scheme Benchmark Programs Sought
To: scheme@mit-mc.ARPA
cc: scheme.users%CSL60%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Tue, 9 Jul 85 21:10 CST

Hello, Un-Common Lisp Lovers:

I am beginning a Scheme performance evaluation project here at TI CSL,
an initial task being to build a suite of benchmark programs. Beyond the
Gabriel Lisp Benchmark Suite translated to Scheme and examples from A&S,
most Scheme programs around these days seem to be "systems" code, e.g.,
compilers and editors.

I am soliciting "applications" code from Scheme users, especially
programs that show off **canonical Scheme programming style**.  I am not
placing any limits a priori on the code size, however, I do request that
source provided conforms to the Revised Revised Report.

What's in it for you? Well, possible enshrinement of your name and all
or part of your favorite program in a "standard" benchmark suite for
Scheme. Also, the good feeling that comes with advancing the cause of
Lisp-Done-Right, since I hope to show off the performance advantages of
the Scheme runtime model.

The ultimate suite of programs will be made available over the net to
interested parties, of course. Thanks for your cooperation.

Regards,

Arthur Altman
Texas Instruments
Computer Science Laboratory
(214) 995-0383

CSNET: altman@ti-csl 
ARPANET: altman%ti-csl@csnet-relay
U.S. Postal Service: M.S. 238, P.O. Box 226015, Dallas, Texas, 75266

-------


∂09-Jul-85  2325	@MIT-MC.ARPA:mw%brandeis.csnet@csnet-relay.arpa 	What cr*p  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Jul 85  23:24:55 PDT
Received: from csnet-relay by MIT-MC.ARPA.ARPA; 10 Jul 85 02:26:14 EDT
Received: from brandeis by csnet-relay.csnet id a016623; 10 Jul 85 2:18 EDT
Received: by brandeis.ARPA (4.12/4.7)
	id AA08833; Tue, 9 Jul 85 22:33:50 edt
Date: 9 Jul 1985 22:27-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: What cr*p
To: dpf%indiana.csnet@csnet-relay.arpa, 
    lang-scheme%indiana.csnet@csnet-relay.arpa, 
    cth%indiana.csnet@csnet-relay.arpa, scheme@mit-mc.ARPA
Message-Id: <489810451/mw@brandeis>

Would you believe that Software: Practice & Experience is about to
publish a paper entitled "On the role of t and nil in Lisp", and whose
abstract is "It is widely believed that McCarthy's interpreter is a
running Lisp program.  It is not, because it does not interpret t and
nil correctly.  We show how to fix this bug."  It's only 2-1/2 pages,
but MUMBLE! 


∂11-Jul-85  2016	GJC@MIT-MC.ARPA 	What cr*p    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 11 Jul 85  20:16:18 PDT
Date: Thu, 11 Jul 85 23:17:53 EDT
From: George J. Carrette <GJC@MIT-MC.ARPA>
Subject:  What cr*p
To: mw%brandeis.csnet@CSNET-RELAY.ARPA
cc: SCHEME@MIT-MC.ARPA, cth%indiana.csnet@CSNET-RELAY.ARPA,
    dpf%indiana.csnet@CSNET-RELAY.ARPA,
    lang-scheme%indiana.csnet@CSNET-RELAY.ARPA
In-reply-to: Msg of 9 Jul 1985 22:27-EST from mw%brandeis.csnet at csnet-relay.arpa
Message-ID: <[MIT-MC.ARPA].572724.850711.GJC>

If you think *thats* bad... a paper on a reference count garbage
collection technique in the ISA conference on expert systems
and robotics this June.
And if you think thats bad you should see the kind of proposals
DOD is getting for "supercomputer lispmachines"

∂19-Jul-85  1756	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford 	CSI Lisp is not tail recursive  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Jul 85  17:55:52 PDT
Received: from mitre-bedford by MIT-MC.ARPA 19 Jul 85 20:56:49 EDT
Date: 19 Jul 1985 20:51:17-EDT
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA25878; Fri, 19 Jul 85 09:48:40 edt
Date: Fri, 19 Jul 85 09:48:40 edt
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8507191348.AA25878@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: CSI Lisp is not tail recursive

An advertisement for CSI Lisp recently appeared in CACM.
The ad states "CSI LISP is a new implementation of T,
which is decended from SCHEME".  For those who don't know,
T is a dialect of SCHEME that is fairly true to SCHEME's
basic ideas.  For example, T programmers are allowed to
assume that evaluation of programs is tail recursive.
Looping constructs generated out of tail recursive
procedures do not increase the size of the stack.

Recent mail to T-DISCUSSION@YALE reveal that CSI Lisp
makes no promise to be tail recursive and is not tail
recursive on implementations that run on top of
Common Lisp and LISP-VM!  I believe Cognitive Systems
must reveal that CSI Lisp is not tail recursive or
it should not associate CSI Lisp with T and SCHEME
in its ads.

In my opinion, a language should, at the very least,
be tail recursive if it is to be associated with SCHEME.
John
PS Ada's name is protected - can anything be done for
SCHEME's name?

∂20-Jul-85  0350	GJC@MIT-MC.ARPA 	truth in advertisement 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Jul 85  03:50:10 PDT
Date: Sat, 20 Jul 85 06:51:14 EDT
From: George J. Carrette <GJC@MIT-MC.ARPA>
Subject:  truth in advertisement
To: SCHEME@MIT-MC.ARPA, linus!ramsdell@MITRE-BEDFORD.ARPA
In-reply-to: Msg of 19 Jul 1985 20:51:17-EDT
      Fri 19 Jul 85 09:48:40 edt from linus!ramsdell at Mitre-Bedford,
      linus!ramsdell (John D. Ramsdell) at Mitre-Bedford
Message-ID: <[MIT-MC.ARPA].582540.850720.GJC>

I think that just about all one can do is send letters to the editors
of the magazines publishing such advertisements. Another thing one can
do is write a letter to the company asking "will your product run the
enclosed program: X" to which they will probably reply yes (because it
will on one implementation). Then you write a letter saying, "great,
here is my $$$ please send me a copy." Then when you get the bogus
copy that wont run your program you say to them: "Please send my money
back." To make it most effective you get 10 or 20 people in on this
doing exactly the same thing. The company wont be as willing to give
back thousands of dollars. Then when they dont give the money back you
go to the Atterny (spell program no help for this word) General's
Office and file a complaint (both state and federal). 10 to 20
complaints are enough to get the feds moving on a
mail-fraud/wire-fraud investigation. The laws protecting consumers
from magazine advertisement mail-order rip-offs are sufficiently
strong to cause server problems to a company in arrears. For one
thing just the act of filing so many complaints can make it
difficult for a small company to raise money from sources that
are smart enough to check for such things. And if things get serious
enough the post office can cut off their mail (quite a screw eh?),
not to mention the criminal penalties that hang over them.

On the other hand, given the effort of making an example of
a company like this, and given how much work it is to do a reasonable
Scheme implementation on top of any halfway decent lisp,
maybe it would be better for us to pitch in and come up with
and advertise for distribution-at-cost some true Scheme implementation?
It would probably be less work (although maybe less fun) than screwing
some losing company to the wall.

-gjc

∂22-Jul-85  1043	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	truth in advertisement 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Jul 85  10:43:49 PDT
Received: from THINK.ARPA by MIT-MC.ARPA 22 Jul 85 13:42:58 EDT
Received: by THINK.ARPA with CHAOS; Mon, 22 Jul 85 13:39:45 edt
Date: Mon, 22 Jul 85 13:41 EDT
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: truth in advertisement
To: GJC@MIT-MC.ARPA, SCHEME@MIT-MC.ARPA, linus!ramsdell@MITRE-BEDFORD.ARPA
Cc: gls@THINK-AQUINAS.ARPA
In-Reply-To: <[MIT-MC.ARPA].582540.850720.GJC>
Message-Id: <850722134121.2.GLS@UBALDO.ARPA>

Well, if you believe that the company is truly sinister and trying to
rip people off with shoddy merchandise, then all the legal apparatus
that GJC describes may be brought to bear.  But it may be that the lack
of tail-recursion is due to incompetence, ignorance, oversight, or maybe
even an intentional tradeoff made to gain something else.  There is a
lot to be said for first writing or calling the company and reporting it
as a bug and politely asking how soon it will be fixed.  What you do
next depends on their reaction.

--Guy

∂22-Jul-85  1522	GJC@MIT-MC.ARPA 	truth in advertisement 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Jul 85  15:22:45 PDT
Date: Mon, 22 Jul 85 18:23:54 EDT
From: George J. Carrette <GJC@MIT-MC.ARPA>
Subject:  truth in advertisement
To: gls@THINK-AQUINAS.ARPA
cc: SCHEME@MIT-MC.ARPA, linus!ramsdell@MITRE-BEDFORD.ARPA
In-reply-to: Msg of Mon 22 Jul 85 13:41 EDT from Guy Steele <gls at THINK-AQUINAS.ARPA>
Message-ID: <[MIT-MC.ARPA].584702.850722.GJC>

I just saw the price of the thing, $10K for the DEC/VAXLISP version.
Now considering the DEC/VAXLISP cost is $12k, charging $10K
for a three or four page lisp program that does syntactic
translation of Scheme code into Common-Lisp code is a bit
absurd. The question is what has been written in "T" that
has that kind of economic value? Evidently a few things!
Or it could be the case of Unix costing $300 from Berkeley
or a Unix emulator under VMS costing you a minimum of $8k.

∂24-Jul-85  1622	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Jul 85  16:22:09 PDT
Received: from mitre-bedford by MIT-MC.ARPA 24 Jul 85 19:20:04 EDT
Date: 24 Jul 1985 17:35:50-EDT
From: linus!ramsdell@Mitre-Bedford
Received: by linus.UUCP (4.12/4.7)
	id AA16213; Wed, 24 Jul 85 08:00:35 edt
Date: Wed, 24 Jul 85 08:00:35 edt
From: linus!ramsdell (John D. Ramsdell)
Message-Id: <8507241200.AA16213@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa

Received: by linus.UUCP (4.12/4.7)
	id AA07000; Tue, 23 Jul 85 07:57:28 edt
Date: Tue, 23 Jul 85 07:57:28 edt
From: ramsdell (John D. Ramsdell)
Message-Id: <8507231157.AA07000@linus.UUCP>
To: bccvax!scheme@mit-mc.arpa
Subject: CSI Lisp
Cc: bccvax!meehan@yale

In my opinion, CSI Lisp was implemented by knowledgeable
people who know very well about tail recursion optimization.
They are not the kind of people that would leave it out
because its too hard to figure out.  In fact, their Apollo
implementation reliably does the optimization.  They left
it out from some implementations because they wanted to port
their programs to machines by implementing their lisp on top
of existing systems.  Since Common Lisp and Lisp-VM are not
required to do the opimization, they realized that they would
incure much pain and suffering if they spend the effort to
get it right in these lisps.  Reasonable people doing 
reasonable things.  My only complaint is that reasonable
people reading their ad in CACM would conclude that all their
implementations are tail recursive.

Cognitive Systems should be applauded for porting a dialect
of lisp that is much simpler than Common Lisp, yet just as
useful.  I think it is important to recognise the good 
with the bad.  Comments and questions about CSI Lisp
should be directed to Jim Meehan (MEEHAN@YALE).
John

∂24-Jul-85  1929	@MIT-MC.ARPA:OXLEY%ti-csl.csnet@csnet-relay.arpa 	Scheme Not Tail Recursive!!!????   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Jul 85  19:26:06 PDT
Received: from csnet-relay by MIT-MC.ARPA 24 Jul 85 22:26:05 EDT
Received: from ti-csl by csnet-relay.csnet id ac16288; 24 Jul 85 7:55 EDT
Date: 23 Jul 1985 1602-CDT
From: Don Oxley <OXLEY%CSL60%ti-csl.csnet@csnet-relay.arpa>
Subject: Scheme Not Tail Recursive!!!????
To: Willc%tekchips%tektronix.csnet@csnet-relay.arpa
cc: Scheme@mit-mc.ARPA
Received: from csl60 by ti-csl; Wed, 24 Jul 85 00:53 CST

In reading the revised, revised report, I can find no statement - either
direct or inferred, that Scheme is required to be properly tail
recursive.  

Did I overlook something?  

I suggest a requirement to that effect be inserted (as an errata if
necessary) on page 8.

A much more picky point.  On page 7, is the statement that ALL objects
have unlimited extent.  Since fluid variables have dynamic extent, it
seems to me that a picky interpretation could preclude fluid variables
in the language (the counter argument of course is that is a sufficient
base to implement fluids).    Would a bit of clarification be helpful?

        --Don

PS.  Sorry for nitpicking AFTER the report is out, but sometimes you
have to be writing your own manual to be able to read another carefully.

-------


∂24-Jul-85  1944	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@csnet-relay.arpa 	Re: Scheme Not Tail Recursive!!!????  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Jul 85  19:43:51 PDT
Received: from csnet-relay by MIT-MC.ARPA 24 Jul 85 22:44:31 EDT
Received: from tektronix by csnet-relay.csnet id ac20001; 24 Jul 85 21:42 EDT
From: Will Clinger <willc%tekchips%tektronix.csnet@csnet-relay.arpa>
To: oxley%ti-csl.csnet@csnet-relay.arpa
Cc: scheme@MIT-MC.ARPA
Received: from tekchips by tektronix with smtp ; 24 Jul 85 17:47:51 PDT
Date: Wednesday, 24 Jul 85 17:33:05 PDT
Subject: Re: Scheme Not Tail Recursive!!!????
In-reply-to: Your message of 23 Jul 1985 1602-CDT.

Finite Memories Considered Harmful (same song, second verse)

Tail recursion  is an  implementation issue  rather than  a matter of
semantics.    Gedanken  experiment:    the   Incredibly  Big  Machine
Corporation  decides that  it can  increase its  profits by compiling
tail recursion improperly while bundling its machines with a contract
that calls for customers to add 10↑13 bytes of RAM each month as part
of preventive maintenance.  

Likewise garbage collection is an implementation issue,  not a matter
of  semantics.    There's  nothing in  the Revised  Revised Report to
mandate a garbage collector.  

On  the  other hand:   Anything  that causes  programs to  run out of
memory is a bug.  

It may be that the Incredibly Big  Machine Corporation  is shipping a
bug-free product.  That  cannot be  said for  any implementation that
uses a finite memory.

It is philosophically inconsistent to insist upon proper treatment of
tail  recursion  and  upon  garbage collection  while allowing finite
memories.  Of course, people know to ask about the  finite memory bug
when they purchase a computer.  Indeed, the bug  is often advertised.
Not  so  many  people know  to ask  about tail  recursion and garbage
collectors, so maybe we should be inconsistent.  

					William Clinger


∂25-Jul-85  0342	@MIT-MC.ARPA:GJS@MIT-OZ 	Re: Scheme Not Tail Recursive!!!????    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Jul 85  03:39:15 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 25 JUL 85  06:39:15 EDT
Date: Thu 25 Jul 85 06:39:18-EDT
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: Scheme Not Tail Recursive!!!????
To: willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA
cc: oxley%ti-csl.csnet@CSNET-RELAY.ARPA, scheme@MIT-MC.ARPA
In-Reply-To: Message from "Will Clinger <willc%tekchips%tektronix.csnet@csnet-relay.arpa>" of Wed 24 Jul 85 22:47:15-EDT

Unless anyone objects, I will insert a one-liner stating that we expect
both tail-recursion and dynamic storage allocation and deallocation are
assumed in any legit implementation (consistent with modern hardware implementations)
-------

∂25-Jul-85  1115	JAR@MIT-MC.ARPA 	Are fluids objects?    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Jul 85  11:15:22 PDT
Date: Thu, 25 Jul 85 14:16:00 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Are fluids objects?
To: OXLEY%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
cc: SCHEME@MIT-MC.ARPA,
    Willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA
Message-ID: <[MIT-MC.ARPA].587507.850725.JAR>

    Date: 23 Jul 1985 1602-CDT
    From: Don Oxley <OXLEY%CSL60%ti-csl.csnet at csnet-relay.arpa>

    A much more picky point.  On page 7, is the statement that ALL objects
    have unlimited extent.  Since fluid variables have dynamic extent, it
    seems to me that a picky interpretation could preclude fluid variables
    in the language (the counter argument of course is that is a sufficient
    base to implement fluids).    Would a bit of clarification be helpful?

I'm no semantics wiz, but I think that "object" is used consistently in
the Scheme and Lisp literature to mean what corresponds to "expressed
value" in denotational semanticses.  Perhaps this point should be made
somewhere.  But I believe that if this point is understood, nothing need
be said about fluids, since they are not necessarily objects (expressed
values).  Anything at all can have dynamic extent if it pleases, as
long as it is not an object.

On the other hand, I don't think the report should preclude language
extensions, and some of these extensions might include various kinds of
second-class citizens, including perhaps objects with only dynamic
extent.  (I don't think I'd do such a thing, but someone else might.)
If other people agree with me on this, maybe some clarification of the
statement on page 7 is in order.

Jonathan

∂25-Jul-85  1125	@MIT-MC.ARPA:JINX@MIT-OZ 	Scheme Not Tail Recursive!!!????  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Jul 85  11:24:56 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 25 JUL 85  14:09:08 EDT
Date: 25 Jul 1985  11:49 EDT (Thu)
Message-ID: <JINX.12129837829.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Don Oxley <OXLEY%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   Scheme@MIT-MC.ARPA, Willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA
Subject: Scheme Not Tail Recursive!!!????
In-reply-to: Msg of 23 Jul 1985  17:02-EDT from Don Oxley <OXLEY%CSL60%ti-csl.csnet at csnet-relay.arpa>

I think we should be fairly harsh about this issue.  I don't consider
an implementation which is not properly tail recursive an acceptable
implementation.  Note also that by properly tail recursive I don't
mean something which just "optimizes" reduction self-calls, but rather
one that keeps a minimum amount of state on any reduction.

I don't understand your objections about the extent of fluid
variables.  I don't think a variable binding is an object, and
certainly in the context of the report there is no way of obtaining it
or manipulating it as an object (so it would not be first class at
least).  Not being an object, its extent can be limited.  However, the
objects being "dynamically bound" must certainly have unlimited
extent.  This difference is similar to the difference between a macro
(whatever that may be), and a macro expander, which is a legitimate
object (probably a procedure).  Both variable bindings and macros are
conceptual entities with no counterpart in the language, the objects
bound to and the macro expanders are "real" objects which are subject
to the same contraints as all other objects.

Note also that even if something has formally unlimited extent, if an
implementation can prove that it is no longer accessible it can
recalim its storage.  This is what gc is based on, but nobody claims
that any implementation must wait until an actual system-wide gc to
reclaim pieces of storage.

∂25-Jul-85  1310	@MIT-MC.ARPA:JINX@MIT-OZ 	previous message   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Jul 85  13:09:52 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 25 JUL 85  16:08:23 EDT
Date: 25 Jul 1985  15:39 EDT (Thu)
Message-ID: <JINX.12129879691.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
Subject: previous message
To:   scheme@MIT-MC.ARPA

I apologize for my previous message, the message does not read as I
expected.  It was certainly not my intent to to alienate anybody.

∂26-Jul-85  1444	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: Scheme Not Tail Recursive!!!????  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Jul 85  14:42:59 PDT
Received: from csnet-relay by MIT-MC.ARPA 26 Jul 85 17:43:23 EDT
Received: from ti-csl by csnet-relay.csnet id ah08928; 26 Jul 85 17:36 EDT
Date: 25 Jul 1985 1055-CDT
From: David Bartley <Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: Scheme Not Tail Recursive!!!????
To: GJS%MIT-OZ@mit-mc.ARPA, willc%tekchips%tektronix.csnet@csnet-relay.arpa
cc: oxley%ti-csl.csnet@csnet-relay.arpa, scheme@mit-mc.ARPA, 
    Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 25-Jul-85 0638-CDT
Received: from csl60 by ti-csl; Thu, 25 Jul 85 13:06 CST

I agree with Don and Gerry.  The standard has to take some notice of the
finiteness of machines (why else have INEXACT?).  Also, the 1978 revised
report specifically states that "Scheme is implemented in such a way that
tail-recursions execute without net growth of the interpreter stack."
Leaving such a statement out of the revised revised report would seem to
imply that the language has changed in that respect.
-------


∂26-Jul-85  2251	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Ambiguous number syntax
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Jul 85  22:50:57 PDT
Received: from csnet-relay by MIT-MC.ARPA 27 Jul 85 01:51:17 EDT
Received: from ti-csl by csnet-relay.csnet id ae10910; 27 Jul 85 1:46 EDT
Date: 26 Jul 1985 1006-CDT
From: David Bartley <Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa>
Subject: Ambiguous number syntax
To: Scheme@mit-mc.ARPA
cc: Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa, 
    MMeyer%CSL60%ti-csl.csnet@csnet-relay.arpa
Received: from csl60 by ti-csl; Fri, 26 Jul 85 18:48 CST

(1) The RRReport states on page 48 that <radix16> is denoted by #h or #H,
while stating on page 50 that the prefix for hex values is #X.  Since
Common Lisp uses #X for "hexadecimal rational" values, we prefer to believe
that the mention of #H on page 48 is a typographical error.  Would anyone
like to argue otherwise?

(2) Is it possible to write a number in base 16 scientific notation?  How
is the letter 'e' or 'E' to be interpreted -- as a hex digit or the start
of the exponentiation suffix?

David Bartley,
Mark Meyer
-------


∂27-Jul-85  1715	@MIT-MC.ARPA:GJS@MIT-OZ 	Re: Ambiguous number syntax   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Jul 85  17:15:17 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 27 JUL 85  20:15:38 EDT
Date: Sat 27 Jul 85 20:14:38-EDT
From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>
Subject: Re: Ambiguous number syntax
To: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
cc: Scheme@MIT-MC.ARPA, MMeyer%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
In-Reply-To: Message from "David Bartley <Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa>" of Fri 26 Jul 85 11:06:00-EDT

I am doing the last pass now...

    (1) The RRReport states on page 48 that <radix16> is denoted by #h or #H,
    while stating on page 50 that the prefix for hex values is #X.  Since
    Common Lisp uses #X for "hexadecimal rational" values, we prefer to believe
    that the mention of #H on page 48 is a typographical error.  Would anyone
    like to argue otherwise?

That was indeed a typo.  I will fix it.


    (2) Is it possible to write a number in base 16 scientific notation?  How
    is the letter 'e' or 'E' to be interpreted -- as a hex digit or the start
    of the exponentiation suffix?

I don't really have a good idea about that.  Perhaps we should defer
any decisions until someone wants to do it! (sounds unlikely).  I actually
hate hex and wish it would go away.
-------

∂29-Jul-85  1020	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Re: Ambiguous number syntax 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Jul 85  10:20:23 PDT
Received: from THINK.ARPA by MIT-MC.ARPA 29 Jul 85 13:11:25 EDT
Received: by THINK.ARPA with CHAOS; Mon, 29 Jul 85 13:07:02 edt
Date: Mon, 29 Jul 85 13:06 EDT
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: Re: Ambiguous number syntax
To: GJS%MIT-OZ@MIT-MC.ARPA, Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
Cc: Scheme@MIT-MC.ARPA, MMeyer%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA,
        gls@THINK-AQUINAS.ARPA
In-Reply-To: The message of 27 Jul 85 20:14-EDT from Gerald Jay Sussman <GJS%MIT-OZ at MIT-MC>
Message-Id: <850729130650.4.GLS@POLYCARP.ARPA>

    Date: Sat 27 Jul 85 20:14:38-EDT
    From: Gerald Jay Sussman <GJS%MIT-OZ@MIT-MC.ARPA>

    I am doing the last pass now...

	(1) The RRReport states on page 48 that <radix16> is denoted by #h or #H,
	while stating on page 50 that the prefix for hex values is #X.  Since
	Common Lisp uses #X for "hexadecimal rational" values, we prefer to believe
	that the mention of #H on page 48 is a typographical error.  Would anyone
	like to argue otherwise?

    That was indeed a typo.  I will fix it.


	(2) Is it possible to write a number in base 16 scientific notation?  How
	is the letter 'e' or 'E' to be interpreted -- as a hex digit or the start
	of the exponentiation suffix?

    I don't really have a good idea about that.  Perhaps we should defer
    any decisions until someone wants to do it! (sounds unlikely).  I actually
    hate hex and wish it would go away.
    -------


I cannot resist passing on one proposal for radix syntax that was
considered for Common Lisp (and rejected, so take it with a grain of
salt!).

First, observe thsat traditional mathematical syntax for a radix is a
trailing subscript:

			1000   =  512
			    8        10

Second, observe that many non-LISP languages uses parentheses or brackets
for subscripting.  Well, we can't use parentheses, so try brackets:

			(EQUAL? 1000[8] 512[10])

For historical compatibility, we also allow 512.  to mean the same as
512[10] .  Therefore "." means the same as "[10]".  So extend this
notion to the floating-point notation:

	3.14159265    means the same as    3[10]14159265

and now we have an unambiguous place to put the radix:

	3[10]1415926535   approximately equals   3[8]11037552


If you really can't stand that, we could settle for 3.11037552[8],
where the "[...]" overrides the decimalness of the ".".

This still doesn't solve the problem of whether "E" is a hex digit or an
exponent marker.  Well, the "E" serves two purposes" as a delimiter
between significand and exponent, and as a precision indicator (other
choices are "D" and perhaps "S", "F", "L", or whatever).  One might wish
to measure precision in bits.  So gobble down "<...>" for this purpose.
Then "E" is just an abbreviation for "<24>" or whatever:

	Pi is approximately [8]311037552<24>+1

If "E" might be taken as a digit, then one must write "<24>" or "<E>".


Pretty horrible, huh?

--Guy

∂30-Jul-85  2036	GJC@MIT-MC.ARPA 	Ambiguous number syntax
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Jul 85  20:35:57 PDT
Date: Tue, 30 Jul 85 22:59:41 EDT
From: George J. Carrette <GJC@MIT-MC.ARPA>
Subject:  Ambiguous number syntax
To: gls@THINK-AQUINAS.ARPA
cc: SCHEME@MIT-MC.ARPA, Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA,
    MMeyer%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA, GJS@MIT-OZ
In-reply-to: Msg of Mon 29 Jul 85 13:06 EDT from Guy Steele <gls at THINK-AQUINAS.ARPA>
Message-ID: <[MIT-MC.ARPA].594615.850730.GJC>

Fortunately there is always #.(J-RANDOM-NUMBER "...random syntax")

∂31-Jul-85  1159	@MIT-MC.ARPA:CPH@MIT-OZ 	identifiers and symbols  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Jul 85  11:58:59 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 31 JUL 85  14:57:20 EDT
Date: Wed, 31 Jul 1985  14:52 EDT
Message-ID: <CPH.12131444141.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Snyder%hplabs.csnet@CSNET-RELAY.ARPA
Cc:   Scheme@MIT-MC.ARPA
Subject: identifiers and symbols
In-reply-to: Msg of 30 Jul 1985  15:54-EDT from Snyder%hplabs.csnet at csnet-relay.arpa

    Date: Tuesday, 30 July 1985  15:54-EDT
    From: Snyder%hplabs.csnet at csnet-relay.arpa
    To:   cph at mit-mc.ARPA
    Re:   identifiers and symbols
    Source-Info: From (or Sender) name not authenticated.

    In reading the draft Scheme report, it appears that the possibility is left
    open for identifiers and symbols to be distinct.  For example, the first
    paragraph in Section II.5 says that symbols are often used to represent
    identifiers, implying that other alternatives are possible.  Is this correct?
    If so, are identifiers defined as objects (how do they behave)?  Does read of
    "X" return an identifier or a symbol?

      Alan Snyder

Technically, these two types might be distinct.  Practically speaking,
there seems little point in doing so.  But there is no reason that the
report should contain this unnecessary bias.

On the other hand, since it is (perhaps) universally true that they
are not distinct, I guess that Will did not think the extra effort of
completely separating them was worth it.  Trying to decide which gets
used where (e.g. in READ) might take some time.  And if you just
assume that they are the same, then (I think) the rest of the report
is pretty consistent.

But I'm just guessing.  I'll forward this to Scheme@MC, which will get
you a much wider range of opinions -- that is the best place to send
mail concerning the report, since everyone who helped make it will be
available to reply.

∂31-Jul-85  1445	JAR@MIT-MC.ARPA 	identifiers and symbols
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Jul 85  14:45:30 PDT
Date: Wed, 31 Jul 85 17:46:03 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  identifiers and symbols
To: Snyder%hplabs.csnet@CSNET-RELAY.ARPA
cc: SCHEME@MIT-MC.ARPA, CPH@MIT-OZ
Message-ID: <[MIT-MC.ARPA].595673.850731.JAR>

    Date: Tuesday, 30 July 1985  15:54-EDT
    From: Snyder%hplabs.csnet at csnet-relay.arpa

    In reading the draft Scheme report, it appears that the
    possibility is left open for identifiers and symbols to be
    distinct.  For example, the first paragraph in Section II.5 says
    that symbols are often used to represent identifiers, implying
    that other alternatives are possible.  Is this correct?  If so,
    are identifiers defined as objects (how do they behave)?  Does
    read of "X" return an identifier or a symbol?

I think you're confusing domains which Lisp blurs, but that the report
takes care to distinguish.  The beginning of section II.1, "special
forms," says that identifiers, whose syntax is given previously, have
two uses (i.e. occur in the grammar in the rhs of two productions): as
<expression>'s, where they name variables; and inside of <datum>'s,
where they notate symbols, a particular kind of value.  Identifiers,
being syntactic, can no more be user-level objects (i.e. values) than
can combinations or special forms.

Your typical Lisp manual (including, I hate to say, the T manual) starts
out the other way around by saying that data (lists, symbols, numbers)
can be notated using character strings of a certain form, and then says
that data can be interpreted as being program: a symbol can be a
variable name, a list can be a combination, etc.  The Scheme report asks
you to imagine that the fact that programs and data are notated pretty
similarly is coincidental.  It never says that a program is "read" from
a file using a READ function, and then parsed and interpreted through a
separate mechanism.  Conceivably some poor soul could translate the
grammar from the Scheme report into YACC, and write a Scheme system in
C, in which maybe identifiers are represented as arrays of small
integers, and symbols and lists never come into existence at all, except
when a (QUOTE ...) form is evaluated, STRING->SYMBOL is called, etc.
The representation of identifiers, like that of numbers, is completely
invisible to the user.

READ of "X" presumably invokes that part of the Scheme parser which
deals with the <datum> nonterminal, and returns the appropriate value,
as if you had evaluated (QUOTE X) instead of (READ ...); so the value
would be a symbol.

I think that the statement in section II.4, "Even Lisp and Scheme
programs are lists," while true in spirit, is not accurate.  But it's
difficult to come up with a concise way to connect the two concepts.
You'd have to say something to the effect that any sequence of terminals
derivable from the nonterminal <expression> could also be derived from the
nonterminal <datum> (can this be inferred from the report?  Can 'foo and
`(a ,b) be derived from <datum>?).

Sorry to be so pedantic... I hope this clarifies things.

Jonathan

∂01-Aug-85  0915	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@csnet-relay.arpa 	Re: identifiers and symbols 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 1 Aug 85  09:14:50 PDT
Received: from csnet-relay by MIT-MC.ARPA  1 Aug 85 12:05:09 EDT
Received: from ti-csl by csnet-relay.csnet id ad01020; 1 Aug 85 11:54 EDT
Date: 31 Jul 1985 1808-CDT
From: David Bartley <Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa>
Subject: Re: identifiers and symbols
To: CPH%MIT-OZ@mit-mc.ARPA, Snyder%hplabs.csnet@csnet-relay.arpa
cc: Scheme@mit-mc.ARPA, Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa
In-Reply-To: Your message of 31-Jul-85 1658-CDT
Received: from csl60 by ti-csl; Wed, 31 Jul 85 19:05 CST

    In reading the draft Scheme report, it appears that the possibility is left
    open for identifiers and symbols to be distinct.  For example, the first
    paragraph in Section II.5 says that symbols are often used to represent
    identifiers, implying that other alternatives are possible.  Is this correct?
    If so, are identifiers defined as objects (how do they behave)?  Does read of
    "X" return an identifier or a symbol?

      Alan Snyder

I think of an "identifier" as a non-terminal in the grammar, while a
"symbol" is a datatype, so identifiers are not objects, and READ of X
returns a symbol.

The reason identifiers and symbols are distinct is that we don't want to
impose the implementation requirement that a Scheme program must be
internally represented as an s-expression.  In particular, an identifier in
a program may be lexically processed by a compiler without passing through
READ at all, and therefore need not be represented as a symbol.  Having
identifiers and symbols obey the same syntax rules is just a way to
facilitate the representation of identifiers by symbols, but it doesn't
require it.

I periodically pick this nit because many non-Schemers confuse "symbols"
with "variables."  Further distinguishing "symbols" from "identifiers" is
meaningful to me, and seems to be implied by Will's wording, but may be
more controversial.  Does anyone else see things this way, or am I outside
the pale (again)?

David Bartley
-------


∂02-Aug-85  1338	@MIT-MC.ARPA:mw%brandeis.csnet@csnet-relay.arpa 	Re: identifiers and symbols    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 2 Aug 85  13:38:38 PDT
Received: from csnet-relay by MIT-MC.ARPA  2 Aug 85 16:39:03 EDT
Received: from brandeis by csnet-relay.csnet id aa09446; 2 Aug 85 16:31 EDT
Received: by brandeis.ARPA (4.12/4.7)
	id AA00810; Fri, 2 Aug 85 11:46:14 edt
Date: 2 Aug 1985 11:39-EST
From: mw%brandeis.csnet@csnet-relay.arpa
In-Real-Life: Mitchell Wand,faculty
Subject: Re: identifiers and symbols
To: David Bartley <Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa>
Cc: scheme@mit-mc.ARPA
Message-Id: <491845196/mw@brandeis>
In-Reply-To: David Bartley's message of 31 Jul 1985 1808-CDT



←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←

	From BARTLEY%ti-csl.csnet%CSNET-RELAY@MIT-MC.ARPA Thu Aug  1 16:24:38 1985
	Date: 31 Jul 1985 1808-CDT
	From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY>
	Subject: Re: identifiers and symbols
	To: CPH%MIT-OZ@MIT-MC, Snyder%hplabs.csnet@CSNET-RELAY
	Cc: Scheme@MIT-MC, Bartley%CSL60%ti-csl.csnet@CSNET-RELAY
	Status: O
	
	    In reading the draft Scheme report, it appears that the possibility is left
	    open for identifiers and symbols to be distinct.  For example, the first
	    paragraph in Section II.5 says that symbols are often used to represent
	    identifiers, implying that other alternatives are possible.  Is this correct?
	    If so, are identifiers defined as objects (how do they behave)?  Does read of
	    "X" return an identifier or a symbol?
	
	      Alan Snyder
	
	I think of an "identifier" as a non-terminal in the grammar, while a
	"symbol" is a datatype, so identifiers are not objects, and READ of X
	returns a symbol.
	
	The reason identifiers and symbols are distinct is that we don't want to
	impose the implementation requirement that a Scheme program must be
	internally represented as an s-expression.  In particular, an identifier in
	a program may be lexically processed by a compiler without passing through
	READ at all, and therefore need not be represented as a symbol.  Having
	identifiers and symbols obey the same syntax rules is just a way to
	facilitate the representation of identifiers by symbols, but it doesn't
	require it.
	
	I periodically pick this nit because many non-Schemers confuse "symbols"
	with "variables."  Further distinguishing "symbols" from "identifiers" is
	meaningful to me, and seems to be implied by Will's wording, but may be
	more controversial.  Does anyone else see things this way, or am I outside
	the pale (again)?
	
	David Bartley
	-------
	
	
	

←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←

Yes, I think you've got it right.  Identifiers are part of the external
syntax of Scheme programs; symbols are a kind of data manipulated by
those programs.  Symbols have an external representation as character
strings, which typically, though not necessarily, coincides with the
external syntax of identifiers.

One of the most important differences between Lisp and Scheme is, as
you point out, the rigid separation between programs and data, and
between syntax and semantics.  Most Lisp dialects constrain programs to
be maintained as S-expressions; Scheme very carefully does not.  For
more on this, see the paper by Muchnick and Pleban, A Semantic
Comparison of Lisp and Scheme, in the 1980 Lisp Conference.

-- Mitch


∂05-Aug-85  1836	@MIT-MC.ARPA:unc!dyb%unc.csnet@csnet-relay.arpa 	Re: identifiers and symbols    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 5 Aug 85  18:35:56 PDT
Received: from csnet-relay by MIT-MC.ARPA  5 Aug 85 21:36:53 EDT
Received: from unc by csnet-relay.csnet id ah10818; 5 Aug 85 21:29 EDT
Received: from unc (dopey) by thorin (4.12/4.7)
	id AA15806; Mon, 5 Aug 85 00:03:04 edt
Received: by unc (4.12/4.7)
	id AA25673; Mon, 5 Aug 85 00:03:23 edt
Date: Mon, 5 Aug 85 00:03:23 edt
From: Kent Dybvig <unc!dyb%unc.csnet@csnet-relay.arpa>
Message-Id: <8508050403.AA25673@unc>
To: Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa, 
    mw%brandeis.csnet@csnet-relay.arpa
Subject: Re: identifiers and symbols
Cc: scheme@mit-mc.ARPA

  In reading the draft Scheme report, it appears that the possibility is left
  open for identifiers and symbols to be distinct.  For example, the first
  paragraph in Section II.5 says that symbols are often used to represent
  identifiers, implying that other alternatives are possible.  Is this correct?
  If so, are identifiers defined as objects (how do they behave)?  Does read of
  "X" return an identifier or a symbol?

  Alan Snyder

    I think of an "identifier" as a non-terminal in the grammar, while a
    "symbol" is a datatype, so identifiers are not objects, and READ of X
    returns a symbol.
      
    The reason identifiers and symbols are distinct is that we don't want to
    impose the implementation requirement that a Scheme program must be
    internally represented as an s-expression.  In particular, an identifier in
    a program may be lexically processed by a compiler without passing through
    READ at all, and therefore need not be represented as a symbol.  Having
    identifiers and symbols obey the same syntax rules is just a way to
    facilitate the representation of identifiers by symbols, but it doesn't
    require it.
      
    I periodically pick this nit because many non-Schemers confuse "symbols"
    with "variables."  Further distinguishing "symbols" from "identifiers" is
    meaningful to me, and seems to be implied by Will's wording, but may be
    more controversial.  Does anyone else see things this way, or am I outside
    the pale (again)?
      
    David Bartley
    -------

  ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
  
  Yes, I think you've got it right.  Identifiers are part of the external
  syntax of Scheme programs; symbols are a kind of data manipulated by
  those programs.  Symbols have an external representation as character
  strings, which typically, though not necessarily, coincides with the
  external syntax of identifiers.
  
  One of the most important differences between Lisp and Scheme is, as
  you point out, the rigid separation between programs and data, and
  between syntax and semantics.  Most Lisp dialects constrain programs to
  be maintained as S-expressions; Scheme very carefully does not.  For
  more on this, see the paper by Muchnick and Pleban, A Semantic
  Comparison of Lisp and Scheme, in the 1980 Lisp Conference.
  
  -- Mitch

←←←←←←←←←←←←←←←←←←

I think that we should point out that certain objects may be
translated into Scheme expressions, with emphasis on translation
(that is, say that it may require writing the object to a file and
handing the compiler the resulting file).  If we loose the idea of
"program as data" people will wonder what we are still using all
these parentheses for.

To allow the potential for translation requires that we agree upon a
common representation for programs as data.  The natural one is the
one that prints the way we expect, with symbols denoting identifiers
and special form keywords.  The wording might go, "If a Scheme object
is to be translated into a Scheme program, identifiers are represented
by symbols, special forms are represented by lists, ..."  This does
require the syntax for identifiers to be a subsyntax (?) of the syntax
for symbols.

In spite of the conclusions of Muchnick and Pleban, I believe that we
should support an object-level representation for Scheme programs.
One of the beauties of Scheme is the ability to write macro processors
and compilers for Scheme in Scheme (easily), and the lack of this
ability is the one thing I dislike most about ML.

Kent


∂05-Aug-85  1851	@MIT-MC.ARPA:CPH@MIT-OZ 	identifiers and symbols  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 5 Aug 85  18:51:22 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 5 AUG 85  21:51:34 EDT
Date: Mon, 5 Aug 1985  21:49 EDT
Message-ID: <CPH.12132830745.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Kent Dybvig <unc!dyb%unc.csnet@CSNET-RELAY.ARPA>
Cc:   Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA,
      mw%brandeis.csnet@CSNET-RELAY.ARPA, scheme@MIT-MC.ARPA
Subject: identifiers and symbols
In-reply-to: Msg of 5 Aug 1985  00:03-EDT from Kent Dybvig <unc!dyb%unc.csnet at csnet-relay.arpa>

    Date: Monday, 5 August 1985  00:03-EDT
    From: Kent Dybvig <unc!dyb%unc.csnet at csnet-relay.arpa>

    I think that we should point out that certain objects may be
    translated into Scheme expressions, with emphasis on translation
    (that is, say that it may require writing the object to a file and
    handing the compiler the resulting file).

I personally am opposed to any mention of files or compilers in such a
manner.  These are completely orthogonal to what I consider the
essence of the programming language (and programming environment), and
serve only the cloud the real issues, not clear them up.  Ideally I
would like an environment without files, and without any explicit
compilation, in which all of that non-essential stuff happens
transparently to me.  I'm interested in writing and debugging
procedures and data structures, not files of characters.

    If we lose the idea of "program as data" people will wonder what
    we are still using all these parentheses for.

Independent of the "program as data" feature, those parentheses are
still an essential aspect of the SIMPLICITY of Scheme (and Lisp)
syntax.  This is, I think, even more important than the fact that a
Scheme program is representable as a data structure.  One can, for
example, represent a Pascal or C program as a data structure in one of
those languages (albeit clumsily), but that does not make the external
syntax any simpler.

    To allow the potential for translation requires that we agree upon a
    common representation for programs as data.

I think that this is completely irrelevant as we have not included the
EVAL procedure in the Scheme standard.  Nothing else in the standard
relates to such a representation in any way.

∂09-Aug-85  1539	JAR@MIT-MC.ARPA 	Altering quoted structure   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Aug 85  15:39:30 PDT
Date: Fri,  9 Aug 85 18:40:58 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Altering quoted structure
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].607100.850809.JAR>

I would like to point out a small problem in an example in section II.4,
"Pairs and lists."  The following interaction:

                (define x '(a b c))     -->  x
                (define y x)            -->  y
                (set-cdr! x 4)          -->  unspecified
                x                       -->  (a . 4)
                (eq? x y)               -->  #!true
                y                       -->  (a . 4)

will not necessarily work in implementations (e.g., Yale's) where quoted
structure may be stored in read-only memory.

I don't think the report says anything about quoted structure being
immutable, but I think that it is very important that implementations be
allowed to make them be read-only.  I recommend that the description of
QUOTE (which is perhaps too terse even for my taste) be amended
appropriately.

The example can easily be fixed: just write

                (define x (list 'a 'b 'c))

instead of

                (define x '(a b c)) .

While the report can only specify that modifying quoted structure "is an
error," I would consider it any implementation which doesn't detect such
modifications to be deficient.  It isn't done because it's difficult.

Jonathan

∂09-Aug-85  1546	JAR@MIT-MC.ARPA 	(EQV? #\? #\?) ?  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Aug 85  15:46:05 PDT
Date: Fri,  9 Aug 85 18:47:31 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  (EQV? #\? #\?) ?
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].607113.850809.JAR>

Could we agree that EQV? should do a CHAR=? comparison on characters?

Jonathan?

∂09-Aug-85  1549	JAR@MIT-MC.ARPA 	Altering quoted structure, addendum   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Aug 85  15:49:49 PDT
Date: Fri,  9 Aug 85 18:51:15 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Altering quoted structure, addendum
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].607118.850809.JAR>

The example

    (define vec '#(0 (2 2 2 2) "Anna")) -->  vec
    (vector-set! vec 1 '("Sue" "Sue"))  -->  unspecified
    vec                                 -->  #(0
                                               ("Sue" "Sue")
                                               "Anna")

is also at fault, and can be fixed the same way as the other one.

Jonathan.

∂09-Aug-85  1618	@MIT-MC.ARPA:JINX@MIT-OZ 	(EQV? #\? #\?) ?   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Aug 85  16:18:48 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 9 AUG 85  19:20:04 EDT
Date: 9 Aug 1985  19:18 EDT (Fri)
Message-ID: <JINX.12133851721.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Jonathan A Rees <JAR@MIT-MC.ARPA>
Cc:   SCHEME@MIT-MC.ARPA
Subject: (EQV? #\? #\?) ?
In-reply-to: Msg of 9 Aug 1985  18:47-EDT from Jonathan A Rees <JAR at MIT-MC.ARPA>

yes!!

∂09-Aug-85  1623	@MIT-MC.ARPA:JINX@MIT-OZ 	Altering quoted structure    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 9 Aug 85  16:23:11 PDT
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 9 AUG 85  19:24:22 EDT
Date: 9 Aug 1985  19:22 EDT (Fri)
Message-ID: <JINX.12133852458.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Jonathan A Rees <JAR@MIT-MC.ARPA>
Cc:   SCHEME@MIT-MC.ARPA
Subject: Altering quoted structure
In-reply-to: Msg of 9 Aug 1985  18:40-EDT from Jonathan A Rees <JAR at MIT-MC.ARPA>

I agree with you even though MIT Scheme does not detect alterations
to quoted structure.  I think the report should say it is an error to
modify them.

PS : What do you do about Gcing quoted structure if it is in read-only
memory?  Is it not garbage-collectable?  Is the garbage collector
special?

∂12-Aug-85  0745	JAR@MIT-MC.ARPA 	delay, force, cons-stream   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Aug 85  07:45:45 PDT
Date: Mon, 12 Aug 85 10:47:18 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  delay, force, cons-stream
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].609180.850812.JAR>

Could someone remind me why DELAY, FORCE, and CONS-STREAM aren't in the
RRReport, even non-essentially?  This absence seems inconsistent with
the presence of SEQUENCE, which exists only because it appears in S&ICP.
DELAY, FORCE, and CONS-STREAM also are used in S&ICP.

Jonathan

∂16-Sep-85  1306	JAR@MIT-MC.ARPA 	report; scheme in CL; trace 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 16 Sep 85  13:06:21 PDT
Date: Mon, 16 Sep 85 16:06:36 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  report; scheme in CL; trace
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].646835.850916.JAR>

[Topic #1:] MIT AI memo 848, the Revised Revised Report on Scheme, is
back from the printer.  The text is exactly the same as what most of you
received in the mail about a month ago, but is is now available in
quantity, and is has a nice binding with a blue cover.  They can be
ordered from:

  Elizabeth Heepe
  Publications, Room NE43-818
  MIT Artifical Intelligence Laboratory
  545 Technology Square
  Cambridge MA 02139

Enclose a check for $6.00 per copy (U.S. funds) payable to the MIT
Artificial Intelligence Laboratory.  If you are strapped for cash or you
need it quickly, I can send you one directly myself, bypassing the
publications office.

[Topic #2:] I have written, as a quick hack, and with the generous
support of DEC, an implementation of the essential subset (and a little
more) of RRRSS, in Common Lisp.  (RRRSS is my abbreviation for Revised
Revised Report on Scheme Scheme.)  It works by translating RRRSS into
Common Lisp; tail recursion is accomplished by compiling calls in a
peculiar way (incompatible with the host Common Lisp's procedure caall,
which will not necessarily be tail recursive at the right time).  If you
are interested in testing it out for me, and sending remarks & bug
reports, I'd be grateful.  The plan is to eventually make this part of
the Common Lisp "Yellow Pages."  I'll mail the source code to anyone
requesting it.

[Topic #3:] I'm curious to know how implementors have dealt with the
problem of causing trace (i.e. debugging) packages to interact properly
with (DEFINE (FOO ...) ...).  I.e. if one says (TRACE FOO) [or (TRACE
'FOO) or whatever your local syntax is], one would like all recursive
calls from FOO to itself to be traced.  Especially tricky to make this
work with native-code compilers.  I think this was one reason why in T
we made (DEFINE (FOO ...) ...) be the same as (DEFINE FOO (LAMBDA (.
...) ...)), instead of using the MIT and RRRSS semantics, because then TRACE
can be implemented at the source code level, as (SET! FOO
(MAKE-TRACED-PROCEDURE FOO)), without any need to know the underlying
representation.  What have other people done?

Jonathan

∂17-Sep-85  1312	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  report; scheme in CL; trace    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Sep 85  13:12:13 PDT
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 17 Sep 85 15:39:06 EDT
Received: from indiana by csnet-relay.csnet id a014789; 17 Sep 85 15:33 EDT
Date: Tue, 17 Sep 85 10:19:37 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: MIT-MC!JAR%unc.csnet@CSNET-RELAY.ARPA, SCHEME@mit-mc.ARPA
Subject: Re:  report; scheme in CL; trace

Chez Scheme supports two interfaces for tracing.  One is
available to the user after his program is entered (the
normal "trace" interface) and the other must be imbedded in
the program ("trace-lambda" or "trace-recur").

"trace" works only as you say, for the outermost invocation
of a function created with "defrec", and not at all for let-
or letrec-bound lambda expressions.  Using "trace-lambda" in
place of "lambda" or "trace-recur" in place of "recur" causes
the same tracing that "trace" provides.

In order to provide the user with a handle on the traced
function, the "trace-lambda" syntax requires an identifier to
precede the formal parameters.

The only disadvantage of "trace-lambda" is that the program
must be reentered to be traced.  This can have a significant
impact on an interactive session unless multiple windows are
provided.

Kent Dybvig
dyb.Indiana@CSnet-Relay


∂22-Oct-85  2253	@MIT-MC.ARPA:meltsner%athena@mit-eddie.MIT.EDU 	Scheme for Thermo.    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Oct 85  22:53:04 PDT
Received: from mit-eddie by MIT-MC.ARPA 21 Oct 85 14:22:10 EDT
Received: from MIT-CHARON (d003a12) by mit-eddie (4.12/4.7)
	id AA25774; Mon, 21 Oct 85 14:19:13 edt
Received: by MIT-CHARON (4.12/4.7)
	id AA02813; Mon, 21 Oct 85 14:23:10 edt
Message-Id: <8510211823.AA02813@MIT-CHARON>
To: scheme@mit-mc, ai-ed@sumex-aim
Cc: meltsner@mit-charon
Subject: Scheme for Thermo.
Date: 21 Oct 85 14:22:51 EDT (Mon)
From: meltsner%athena@mit-eddie.MIT.EDU


This is both a request and an announcement:

I have been working on a "microworld" for thermodynamics.  The world
would support common thermodynamic objects like gases and solids, and would
allow objects to be interconnected, and equilibriums found with a variety
of constraints on mass, energy, volume, etc. transfer.  ("would" because
not all features have been implemented)

It has proved to be useful in an introductory (graduate) level thermo course,
and I am currently planning to rewrite it to remedy a number of deficiencies.

Questions:

1)  Would you prefer an english-language (command-driven) interface or a
windowed one?  Does "make an gas with 10 moles of neon temperature 298" make
more sense than a dialog box after one has selected a menu item "Make Gas"?

2)  Are windowed graphics useful?  What sort of graphics?(x-time, x-y, contour,
dials, gauges, empty/full bar indicators)

3)  Would you sacrifice speed for numeric accuracy? (1% accuracy vs. .01% might
triple the iteration time)

4)  How important are on-line help, explanations of internal processes,
examples?

5)  What would you like to have it run on?  (4.2 Unix, Macintosh, IBM, ??)

6)  What would it have to run on to be useful for use in a class at your
institution?

The program is currently written in T, and will be moved to Cscheme (MIT
Vax 4.2 Unix Scheme in C).

The program is available for trade or (in a few months) for a nominal
fee from our group at MIT.  Planned expansions include the ability to
change thermodynamic state variables, a thermo methods database
(rule-driven thermo), and a clock for kinetic problems.

Please send all answers and questions to:

meltsner@athena.MIT.EDU

or Ken Meltsner
   MIT Room 13-5142
   Cambridge, MA 02139         617-253-3139


				Ken

∂22-Oct-85  2253	JAR@MIT-MC.ARPA 	scheme implementations 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Oct 85  22:53:33 PDT
Date: Mon, 21 Oct 85 16:08:06 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  scheme implementations
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].687283.851021.JAR>

To make sure that everyone out there has current information, I want to
ask people who have or are actively working on Scheme implementations to
send out a SHORT message, giving the following information:

- Name of implementation
- Implemented by whom
- Supported by whom, and to what extent
- Hardware and operating system(s)
- Availability: when, approximate pricing, copyright status
- Description of dialect (esp. compare with RRRSS [*] and with the
  dialect used in S&ICP)
- Intended use: education, number crunching, systems programming, etc.
- Implementation style (S-code, native-code-compiler-based, or whatever)
- Remarks, interesting features, misfeatures, and applications, etc.
- Whom to contact for more information

In particular, I'd like to hear blurbs from the groups at Indiana, MIT,
Semantic Microsystems, TI, Yale, Vincennes, and Cadence.  No hype please.

[* Sorry, I use the following abbreviations:
     S&ICP = the book "Structure and Interpretation of Computer Programs"
	     by Abelson & Sussman
     RRRSS = the Scheme dialect described in the Revised Revised Report
     ERRRSS = the "essential" subset of RRRSS]

If you have written books or articles about or using Scheme or are in
the process of doing so, I think people would be interested in hearing
about that too.

∂22-Oct-85  2334	JAR@MIT-MC.ARPA 	welcome 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Oct 85  23:34:05 PDT
Date: Sun, 20 Oct 85 21:46:23 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  welcome
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].686441.851020.JAR>

Welcome to the "Scheme" mailing list.  The list is intended to be a
forum for discussing anything related to the Scheme programming
language(s), with particular emphasis on the use of Scheme in education.
There are over 100 people on the list now, with about 70 institutions
represented.  Most have signed up as the result of a recent message
on AILIST.

Send all communication concerning the administration of the list
(additions, removals) to Scheme-Request@MIT-MC.

Some of you may be unwittingly on this list (e.g., indirectly through
some other list).  Send mail to Scheme-Request@MIT-MC if you don't want
to be on and I'll try to fix things somehow.

Messages will accrete in the file "LSPMAI; SCHEME MAIL" on MIT-MC.

Several people have asked about MIT AI memo 848, the "Revised Revised
Report on Scheme," Will Clinger, editor.  It can be ordered from:

  Elizabeth Heepe
  Publications, Room NE43-818
  MIT Artifical Intelligence Laboratory
  545 Technology Square
  Cambridge MA 02139

Enclose a check for $6.00 per copy (U.S. funds) payable to the MIT
Artificial Intelligence Laboratory.

Coming soon: information on available and unavailable Scheme
implementations.

Jonathan Rees
JAR@MIT-MC

∂22-Oct-85  2351	JAR@MIT-MC.ARPA 	Implementation blurb: Scheme in Common Lisp
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Oct 85  23:51:21 PDT
Date: Mon, 21 Oct 85 20:27:49 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Implementation blurb: Scheme in Common Lisp
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].687556.851021.JAR>

    - Name of implementation:
CLSCH (Scheme embedded in Common Lisp)
    - Implemented by whom:
Jonathan Rees
    - Supported by whom, and to what extent:
Unsupported, although I'll probably continue to improve it.  No promises.
    - Hardware and operating system(s):
Will run in any implementation of Common Lisp.
    - Availability:
In alpha-test now (looking for guinea pigs).  Free.  Distributed as
source via electronic mail or FTP.  (I won't make tapes.)  May
eventually become part of Common Lisp "Yellow Pages."
    - Description of dialect:
Subset.  All of the essential features of RRRSS exist, except for a
correct CALL-WITH-CURRENT-CONTINUATION (some of you will say that it's
not Scheme at all, and I don't disagree); also some of the rest of
RRRSS, and most of the S&ICP dialect.
    - Intended use:
Running existing ERRRSS programs in any Common Lisp.  Not an ideal
development system, since debugging tools are weak.
    - Implementation style:
Low-tech.  A simple compiler translates Scheme into Common Lisp, making
sure that variable binding and tail recursion are done right.  The
output of the compiler can be interpreted by a CL interpreter or
compiled by a CL compiler.
    - Remarks:
I did this mostly for my own personal use.  Maybe other people will find
it useful too.
    - Contact:
Jonathan Rees (JAR@MIT-MC), MIT Artificial Intelligence Laboratory,
545 Technology Square, Cambridge MA 02139, (617) 253-8581.

∂23-Oct-85  2107	JAR@MIT-MC.ARPA 	Implementation blurb: Vincennes Scheme
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Oct 85  21:07:25 PDT
Date: Thu, 24 Oct 85 00:08:44 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Implementation blurb: Vincennes Scheme
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].690739.851024.JAR>

Since I doubt anyone from Univ. de Paris 8 is on this list, I'll send
out what information I have on Vincennes Scheme.
					- Jonathan
---

Vincennes Scheme is a version of Scheme written entirely in portable
C, for Unix V7 and Berkeley 4.1 and 4.2.  It runs on 32-bit machines
(e.g. 68K or Vax) as well as on 16-bit machines (e.g. Z8000 in which
it can fit in 128K).  This Scheme is compatible with the MIT version,
and includes an interpreter with the basic environment: debugger,
history, break, stepper, where. A compiler that generates C code is
available.  For more information, contact

Patrick Greussay
Universite Paris-8-Vincennes
2 rue de la Liberte
Saint-Denis CEDEX 02 93526
France

∂23-Oct-85  2322	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Elementary question about backquote in T.   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 23 Oct 85  23:22:02 PDT
Received: from rand-unix.ARPA by MIT-MC.ARPA 24 Oct 85 01:02:18 EDT
Return-Path: <narain@rand-unix.ARPA>
Received: by rand-unix.ARPA; Wed, 23 Oct 85 21:59:52 pdt
From: Sanjai Narain <narain@rand-unix.ARPA>
Message-Id: <8510240459.AA18070@rand-unix.ARPA>
Date: 23 Oct 85 21:59:49 PDT (Wed)
To: scheme@mit-mc
Subject: Elementary question about backquote in T.


I hope it is okay to send a T question to this list, since I am not aware
of a separate list for T.

If we define:

	(define-macro (bar x) `(list ,(car x)))

then (macro-expand '(bar '(1 2)) *scratch-env*) ==> (list quote). That is, an
attempt to evaluate (bar '(1 2)) will give an error to the effect that
quote is unbound.

This appears to me rather confusing. A macro is ideally a rewrite rule.
So I expect (bar '(1 2)) to be rewritten to the form (list u) where
u = (car '(1 2)) i.e. (list u) must be rewritten to (list 1).
This expectation is supported by the following observations:

       >  (set x '(1 2))
	  ;; x is bound to '(1 2)

       > `(list ,(car x))

	  ==> (list 1)

What am I missing? By the way, Franzlisp backquote behaves similarly.

Thanks for any comments.

-- Sanjai

∂24-Oct-85  0856	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Elementary question about backquote in T.  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Oct 85  08:56:36 PDT
Received: from GODOT.THINK.COM by MIT-MC.ARPA 24 Oct 85 11:57:26 EDT
Received: from jehosephat by GODOT.THINK.COM via CHAOS; Thu, 24 Oct 85 11:57:31 edt
Date: Thu, 24 Oct 85 11:59 EDT
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: Elementary question about backquote in T.
To: narain@RAND-UNIX.ARPA, scheme@MIT-MC.ARPA
Cc: gls@THINK-AQUINAS.ARPA
In-Reply-To: <8510240459.AA18070@rand-unix.ARPA>
Message-Id: <851024115916.2.GLS@THINK-JEHOSEPHAT.ARPA>

    Date: 23 Oct 85 21:59:49 PDT (Wed)
    From: Sanjai Narain <narain@rand-unix.ARPA>
    ...
    If we define:

	    (define-macro (bar x) `(list ,(car x)))

    then (macro-expand '(bar '(1 2)) *scratch-env*) ==> (list quote). That is, an
    attempt to evaluate (bar '(1 2)) will give an error to the effect that
    quote is unbound.

    This appears to me rather confusing. A macro is ideally a rewrite rule.
    So I expect (bar '(1 2)) to be rewritten to the form (list u) where
    u = (car '(1 2)) i.e. (list u) must be rewritten to (list 1).

No, u = (car ''(1 2)).

    This expectation is supported by the following observations:

	   >  (set x '(1 2))
	      ;; x is bound to '(1 2)

No, x is bound to (1 2).  The car of this is then 1.

	   > `(list ,(car x))

	      ==> (list 1)

    What am I missing? By the way, Franzlisp backquote behaves similarly.

    Thanks for any comments.

    -- Sanjai

For absolute precision, in the following remarks I will use
double-quotes as metasyntactic quote marks, rather than as string
delimiters.

In the macro call "(bar '(1 2))" the macro parameter "x" is bound to an
unevaluated argument, so the value of "x" is "'(1 2)", which is the same
as "(quote (1 2))".  When you write ",(car x)" within the backquote, it
means to take the car of the macro-expand-time value of "x".  The value
of "x" is "(quote (1 2))", so the car of that is "quote".

The resdult of expanding "(bar (1 2))" (without a single quote) would be
"(list 1)", which wpould then evaluate to "(1)".

One could also define "bar" as

	    (define-macro (bar x) `(list (car ,x)))

with the comma in a different place, so as to make the "car" operation
take place at evaluation time (run time) rather than expansion time
(compile time).  Then the macro call "(bar '(1 2))" would expand to
"(list (car '(1 2)))" which would in turn also evaluate to "(1)".

--Guy

∂24-Oct-85  1201	@MIT-MC.ARPA:RAM@YALE.ARPA 	Re: Elementary question about backquote in T.  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Oct 85  11:17:01 PDT
Received: from yale by MIT-MC.ARPA 24 Oct 85 14:00:07 EDT
Received: by Yale-Bulldog.YALE.ARPA; 24 Oct 85 13:31:16 EDT (Thu)
Message-Id: <8510241731.AA00535@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 24 Oct 85 13:06:11 EDT
Subject: Re: Elementary question about backquote in T.
Date: Thu, 24 Oct 85 13:06:14 EDT
From: Ashwin Ram <Ram@YALE.ARPA>
To: Sanjai Narain <narain@RAND-UNIX>
Cc: scheme@MIT-MC
In-Reply-To: Sanjai Narain <narain@rand-unix.ARPA>, 23 Oct 85 21:59:49 PDT (Wed)

I'm sure you'll get a lot of responses to your question, but anyway...

    
    I hope it is okay to send a T question to this list, since I am not aware
    of a separate list for T.
    
There are two:  T-USERS and T-DISCUSSION.  There was once a reason for having
separate lists but in practice everyone now reads both and there doesn't seem
to be any real difference in the type or level of questions.

    If we define:
    
    	(define-macro (bar x) `(list ,(car x)))
    
    then (macro-expand '(bar '(1 2)) *scratch-env*) ==> (list quote). That is, an
    attempt to evaluate (bar '(1 2)) will give an error to the effect that
    quote is unbound.
    
    This appears to me rather confusing. A macro is ideally a rewrite rule.
    So I expect (bar '(1 2)) to be rewritten to the form (list u) where
    u = (car '(1 2)) i.e. (list u) must be rewritten to (list 1).
    This expectation is supported by the following observations:
    
           >  (set x '(1 2))
    	  ;; x is bound to '(1 2)
    
           > `(list ,(car x))
    
    	  ==> (list 1)
    
    What am I missing? By the way, Franzlisp backquote behaves similarly.
    
    Thanks for any comments.
    
    -- Sanjai
    ---------

The single-quote character is a read macro that wraps a QUOTE around its
argument.  In T terms, that means the following:
  
    > (stream-read-table (standard-input))
    #{Read-table 53 *STANDARD-READ-TABLE*}
    > (read-table-entry (stream-read-table (standard-input)) #\')
    #{Procedure 54 READ-QUOTATION}

and, from TSYS/READ.T:

    (DEFINE (READ-QUOTATION STREAM CH RT)
       (IGNORE CH)
       (LIST *QUOTE* (READ-OBJECT-REFUSING-EOF STREAM RT)))

Thus '(1 2) gets read in as (QUOTE (1 2)), and (bar '(1 2)) expands to
(LIST u) where u is the CAR of (QUOTE (1 2)), i.e., the symbol QUOTE.
In other words, (bar '(1 2)) expands to (list QUOTE) as you noted.

Macros are rewrite rules, but on list structures (like "(QUOTE (1 2))"), not
on ASCII text (like "'(1 2)").  In your transcript, x gets bound, not to
"'(1 2)" as you say, but to a list structure represented as (1 2).  The CAR
of this structure is the atom 1, and thus you get (list 1), i.e., the list
(1) as your result.

Hope this helps... Ashwin.


-------

∂24-Oct-85  1331	JAR@MIT-MC.ARPA 	T mailing lists.  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Oct 85  13:30:47 PDT
Date: Thu, 24 Oct 85 16:31:38 EDT
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  T mailing lists.
To: narain@RAND-UNIX.ARPA
cc: SCHEME@MIT-MC.ARPA
In-reply-to: Msg of Thu 24 Oct 85 13:06:14 EDT from Ashwin Ram <Ram at YALE.ARPA>
Message-ID: <[MIT-MC.ARPA].691724.851024.JAR>

I'll put you, and anyone else who wants to be, on the T lists.  I think
their existence is mentioned in the front of the T Manual.  In general,
requests should be sent to T-Discussion-Request@MIT-MC.  (T-Users was
intended as a one-way communications channel from implementors to users
for announcements, etc., and T-Discussion was intended to be a forum.)

∂24-Oct-85  1443	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Q. on backquote    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 24 Oct 85  14:43:13 PDT
Received: from rand-unix.ARPA by MIT-MC.ARPA 24 Oct 85 15:32:29 EDT
Return-Path: <narain@rand-unix.ARPA>
Received: by rand-unix.ARPA; Thu, 24 Oct 85 12:18:48 pdt
From: Sanjai Narain <narain@rand-unix.ARPA>
Message-Id: <8510241918.AA29049@rand-unix.ARPA>
Date: 24 Oct 85 12:18:45 PDT (Thu)
To: scheme@mit-mc
Subject: Q. on backquote


Thanks to all of you for taking the time to respond to my question. I realize
much of what you say for I have been using the facility for quite a while.
My intention was to understand it precisely. Fundamentally, it is a question
of what is the need to quote and what is evaluation. Note that Prolog
doesn't need to quote, neither does the lambda calculus.

-- Sanjai

∂25-Oct-85  0945	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: Q. on backquote 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Oct 85  09:45:11 PDT
Received: from yale by MIT-MC.ARPA 25 Oct 85 10:23:27 EDT
Received: by Yale-Bulldog.YALE.ARPA; 25 Oct 85 10:10:52 EDT (Fri)
Message-Id: <8510251410.AA08341@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Fri, 25 Oct 85 10:10:41 EDT
Subject: Re: Q. on backquote
Date: Fri, 25 Oct 85 10:10:42 EDT
From: Paul Hudak <Hudak@YALE.ARPA>
To: Sanjai Narain <narain@RAND-UNIX>
Cc: scheme@MIT-MC
In-Reply-To: Sanjai Narain <narain@rand-unix.ARPA>, 24 Oct 85 12:18:45 PDT (Thu)

    ...
    Fundamentally, it is a question of what is the need to quote and
    what is evaluation.  Note that Prolog doesn't need to quote, neither
    does the lambda calculus.
    
Please -- T/Scheme doesn't need to quote either -- one can usually
use closures to do what you want.  It's just that macros are useful
for defining *syntax*, and there's no reason that Prolog designers
won't reach the same conclusion.  Although I personally shy away from
using macros, they are generally viewed as a *feature* of Lisps, but
not necessarily fundamental to the language or its semantics.

        -Paul

∂26-Oct-85  1019	@MIT-MC.ARPA:WAXMAN@USC-ECL.ARPA 	PLASE REMOVE MY NAME FROM SCHEME MAILING LIST 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Oct 85  10:05:43 PDT
Received: from USC-ECL.ARPA by MIT-MC.ARPA 26 Oct 85 13:06:47 EDT
Date: 26 Oct 1985 1002-PDT
From: WAXMAN@USC-ECL.ARPA
Subject: PLASE REMOVE MY NAME FROM SCHEME MAILING LIST
To:   JAR@MIT-MC.ARPA
cc:   SCHEME@MIT-MC.ARPA

JONATHON,
PLEASE REMOVE MY NAME FROM THE SCHEME ELECTRONIC MAIL LIST.
IT HAS MORE DETAIL THAN I NEED.
THANKS,
MILT WAXMAN
WAXMAN@USC-ECLA
-------

∂28-Oct-85  0740	JAR@MIT-MC.ARPA 	moderation   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  07:40:25 PST
Date: Mon, 28 Oct 85 10:41:43 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  moderation
To: SCHEME@MIT-MC.ARPA
In-reply-to: Msg of 27 Oct 85 00:21:50 EDT (Sun) from yba at ATHENA.MIT.EDU
Message-ID: <[MIT-MC.ARPA].695148.851028.JAR>

I have received several messages of the following form:

    Date: 27 Oct 85 00:21:50 EDT (Sun)
    From: yba at ATHENA.MIT.EDU

    Or could we at least get it moderated so as to ensure it
    discusses scheme instead of backquotes in T?  How about just
    asking folks not to cc the entire list?  Please?

If you have any doubt as to whether a message you want to send is
appropriate for the list, send it to SCHEME-REQUEST@MIT-MC, and I'll
either forward it or reply to it.  For the moment, I'll act as
"moderator" when that's needed.  I don't want to spend too much time
on this, so please, moderate yourselves.  Remember that turnaround can
be very slow, since many people are only connected through CSNET or
uucp.  That explains why there were redundant replies to the backquote
question.

In defense of the recent backquote flurry, I'll say that the question
had nothing to do with T; backquote is a common feature of RRRSS, Common
Lisp, and many other Lisps.  However, I agree that the question had
little to do with Scheme either.  My perception is that most people are
on the list not because they're interested in language issues per se,
but rather because they want to talk about how people actually use the
unique aspects of Scheme in teaching and discussing computation.  (Tell
me if I'm wrong.)

∂28-Oct-85  0824	JAR@MIT-MC.ARPA 	implementations   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  08:24:21 PST
Date: Mon, 28 Oct 85 11:25:33 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  implementations
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].695198.851028.JAR>

Since no one has responded to my request for implementation info, I'll
send out excerpts from the standard letter that MIT sends to people who
ask about Scheme implementations.  I hope this is useful to some of you.

Some of this information may be out of date.  Please correct whatever's
wrong.  I didn't include the paragraph on Chez Scheme since it gave a
UNC address and phone number, and it was my understanding that Chez
Scheme now comes from Cadence Research Inc., not UNC.  Also, I don't
know who the official contact, if any, is for T.  Information on the MIT
scheme implementations was too detailed, and most of you probably have
it already, so a condensed version will arrive under separate cover.

- Jonathan


@b[MacScheme] is a commercially-available implementation of Scheme for
the 512K Apple Macintosh. It meets the requirements of the Revised
Revised Report.  A compatibility file is supplied for use with the
Abelson and Sussman book.  The system features a byte-code interpreter
and Macintosh-style user interface.  MacScheme sells for $125; site
licenses are available.  For more information, write to:
@begin(display)
Semantic Microsystems
1001 Bridgeway Suite 543
Sausalito CA 94965
(415) 332-8094
@end(display)

@b[PC Scheme] (unofficial name) is an implementation of Scheme that is
being developed at Texas Instruments.  It runs on the Texas
Instruments Personal Computer and the IBM Personal Computer.  Besides
the Scheme interpreter itself, the system includes graphics, windowing
capabilities, and a text editor implemented in Scheme.  The
implementation adheres to the Scheme standard, and it is completely
compatible with the MIT course material.  The Scheme interpreter
itself will run in 256K, but successful course use (easily invoking
the editor, loading the largest MIT material) requires a system with
at least 512K and preferably a hard disk.  PC Scheme is still under
development and is not available commercially.  However, Texas
Instruments is conducting an instructional beta test program under
which they will make implementations available to institutions wishing
to use Scheme in conjunction with courses and other instructional
projects.  For information on the program contact
@begin(display)
Texas Instruments 
PO Box 2909 
Austin, Texas  78769 
Attn:  Scheme Product Center,  M/S 2244 
@end(display)

@b[Scheme84] is a version of Scheme that has been under development at
Indiana University for the past few years, and is used there to
support half a dozen different computer science courses.  The system
runs on the Vax under either VMS or Berkeley Unix.  The developers of
Scheme84 intend to supply a compatibility package that will allow the
MIT materials to be run without modification.  The Scheme84 software
is in the public domain, and can be obtained by writing to@foot{The
current distribution policy for Scheme84 is that Indiana University
will supply it for free, if you send them a tape and return postage.
(Please specify whether the system is to be for VMS or for Unix.)  On
the other hand, the University reserves the right to begin charging a
fee to recover the cost of distribution, should this become
necessary.}
@begin(display)
Scheme84 Distribution
Nancy Garrett
c/o Dan Friedman
Department of Computer Science
Indiana University
Bloomington, Indiana
(812)-335-9770
E-mail address nlg@@indiana
@end(display)

@b[T] is a version of Scheme that was developed at Yale University, and is
available for distribution.  The system runs on Vaxes under VMS or
Unix (Berkeley 4.1 or 4.2) and on the Apollo Domain.  For more
information, contact [???] at Yale (203-436-0802) or write to
@begin(display)
Yale University Dept. of Computer Science
PO Box 2158
Yale Station 
New Haven, CT 06520
@end(display)

∂28-Oct-85  1024	JAR@MIT-MC.ARPA 	implementations   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  10:24:22 PST
Date: Mon, 28 Oct 85 13:25:34 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  implementations
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].695199.851028.JAR>

Since no one has responded to my request for implementation info, I'll
send out excerpts from the standard letter that MIT sends to people who
ask about Scheme implementations.  I hope this is useful to some of you.

Some of this information may be out of date.  Please correct whatever's
wrong.  I didn't include the paragraph on Chez Scheme since it gave a
UNC address and phone number, and it was my understanding that Chez
Scheme now comes from Cadence Research Inc., not UNC.  Also, I don't
know who the official contact, if any, is for T.  Information on the MIT
scheme implementations was too detailed, and most of you probably have
it already, so a condensed version will arrive under separate cover.

- Jonathan


@b[MacScheme] is a commercially-available implementation of Scheme for
the 512K Apple Macintosh. It meets the requirements of the Revised
Revised Report.  A compatibility file is supplied for use with the
Abelson and Sussman book.  The system features a byte-code interpreter
and Macintosh-style user interface.  MacScheme sells for $125; site
licenses are available.  For more information, write to:
@begin(display)
Semantic Microsystems
1001 Bridgeway Suite 543
Sausalito CA 94965
(415) 332-8094
@end(display)

@b[PC Scheme] (unofficial name) is an implementation of Scheme that is
being developed at Texas Instruments.  It runs on the Texas
Instruments Personal Computer and the IBM Personal Computer.  Besides
the Scheme interpreter itself, the system includes graphics, windowing
capabilities, and a text editor implemented in Scheme.  The
implementation adheres to the Scheme standard, and it is completely
compatible with the MIT course material.  The Scheme interpreter
itself will run in 256K, but successful course use (easily invoking
the editor, loading the largest MIT material) requires a system with
at least 512K and preferably a hard disk.  PC Scheme is still under
development and is not available commercially.  However, Texas
Instruments is conducting an instructional beta test program under
which they will make implementations available to institutions wishing
to use Scheme in conjunction with courses and other instructional
projects.  For information on the program contact
@begin(display)
Texas Instruments 
PO Box 2909 
Austin, Texas  78769 
Attn:  Scheme Product Center,  M/S 2244 
@end(display)

@b[Scheme84] is a version of Scheme that has been under development at
Indiana University for the past few years, and is used there to
support half a dozen different computer science courses.  The system
runs on the Vax under either VMS or Berkeley Unix.  The developers of
Scheme84 intend to supply a compatibility package that will allow the
MIT materials to be run without modification.  The Scheme84 software
is in the public domain, and can be obtained by writing to@foot{The
current distribution policy for Scheme84 is that Indiana University
will supply it for free, if you send them a tape and return postage.
(Please specify whether the system is to be for VMS or for Unix.)  On
the other hand, the University reserves the right to begin charging a
fee to recover the cost of distribution, should this become
necessary.}
@begin(display)
Scheme84 Distribution
Nancy Garrett
c/o Dan Friedman
Department of Computer Science
Indiana University
Bloomington, Indiana
(812)-335-9770
E-mail address nlg@@indiana
@end(display)

@b[T] is a version of Scheme that was developed at Yale University, and is
available for distribution.  The system runs on Vaxes under VMS or
Unix (Berkeley 4.1 or 4.2) and on the Apollo Domain.  For more
information, contact [???] at Yale (203-436-0802) or write to
@begin(display)
Yale University Dept. of Computer Science
PO Box 2158
Yale Station 
New Haven, CT 06520
@end(display)

∂28-Oct-85  1158	@MIT-MC.ARPA:narain@rand-unix.ARPA 	Re: moderation
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  11:57:56 PST
Received: from rand-unix.ARPA by MIT-MC.ARPA 28 Oct 85 14:57:35 EST
Return-Path: <narain@rand-unix.ARPA>
Received: by rand-unix.ARPA; Mon, 28 Oct 85 10:24:33 pst
From: Sanjai Narain <narain@rand-unix.ARPA>
Message-Id: <8510281824.AA14691@rand-unix.ARPA>
Date: 28 Oct 85 10:24:25 PST (Mon)
To: scheme@mit-mc
Subject: Re: moderation
In-Reply-To: Your message of Mon, 28 Oct 85 10:41:43 EST.
	     <[MIT-MC.ARPA].695148.851028.JAR>


The question I asked is not as trivial as it sounds to people who
seem to have objected to it. It has to do with the necessity of quoting
expressions, something which is absent from other systems such as Prolog.

Hudak made the mysterious comment that Scheme/T doesn't need
to quote either. Well, if you want to set x to the symbol a try typing
(set x a). In Prolog you can do X=a quite legitimately. The problem
is simply that in Lisps there is no way of distinguishing variables from
constant symbols of the same name. So, you must use quote. The matter
is further complicated in the use of backquotes and by the dubious
distinction between evaluation and macroexpansion. What is the purpose of
this distinction? In the lambda calculus evaluation is simply repeated
macroexpansion to the normal form.

What distinguishes Scheme/T from other Lisps but language issues such
as lexical scoping and higher order functions? Yes, what indeed? If people
don't seem to be interested in discussing such issues here, as Jonathan
implies, I understood the purpose of  this list quite incorrectly. Sorry.

FYI hardly anyone objects like yba@athena.mit in other language-oriented
lists like Prolog, or Franz-friends.

-- Sanjai

∂28-Oct-85  1359	@MIT-MC.ARPA:bap@g.cs.cmu.edu 	Re: need for quoting in Lisp 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  13:58:05 PST
Received: from G.CS.CMU.EDU by MIT-MC.ARPA 28 Oct 85 16:51:34 EST
Date: 28 Oct 1985 16:07-EST 
From: Barak.Pearlmutter@G.CS.CMU.EDU
To: scheme@mit-mc
Subject: Re: need for quoting in Lisp
Message-Id: <499381673/bap@G.CS.CMU.EDU>

At first glance it seems odd that Lisp requires quoting while Prolog
and lambda-calculus do not.  The reason is that Lisp attempts to be
it's own meta-language, allowing chunks of code to be treated as data.
This power carries with it the danger that code and data might be
confused, and QUOTE is the way in which the confussion is averted.  To
illustrate very concretely, imagine a Schemelike language which is NOT
it's own metalanguage, in which there are no macros.  For any
construct, we can tell unambiguously whether we have code or data
in our hands, and hence quoting will be unnecessary.

Let's call our emasculated Scheme Scheme0.  In Scheme0, the symbols
manipulated by code will not be used to represent variables.  Rather,
we will have two different kinds of symbols, which both have the
identity property but are distinguished.  The read/print convention I
use will be that v-symbols will be lower case and d-symbols will be
upper case.  V-symbols will never be allowed into data structures
manipulated by code; rather they can only be part of programs
themselves.

Similarly, we will have two different kinds of cons cells: the cons
cells that make up the lists used to represent function calls and
special forms, and another kind of cons cell used to construct lists
manipulated by Scheme0 programs.  The read/print convention for these
will be that program cons cells use (...) and data cons cells use
[...].  We now have a situation much like that with numbers and strings
in regular lisps: data cons cells can never be used to mean program, so
need not be quoted, and similarly with data symbols.  Semantics by
example:

	Regular Scheme				Scheme0

 (car (append x y))			(car (append x y))

 (car (quote (append x y)))		(car [APPEND X Y])

 (append (f x) (g (quote y))		(append (f x) (g Y) [H Z])
         (quote (h z)))

 (f (lambda (x) (f x (quote (f x)))))	(f (lambda (x) (f x [F X])))

There are many routes to add metarepresentational power to Scheme0.
One is to identify v-symbols with d-symbols, and the same with lists,
thus requiring QUOTE to distinguish constants from code, but allowing
macros to be written.  Another would be to force macros to be written
in another language, say Scheme0-1, which can manipulate both v-data
and d-data, and is written using v-prime-datatypes.  Unfortunately,
this requires more and more datatypes as we move up levels in the
tower.  Thus, a DOLIST macro written to apply to Scheme0 code would be
written in Scheme0-1, but then DOLIST couldn't be used in Scheme0-1
unless you rewrote it in Scheme0-2, etc.  There is a way out of this
dilemma, as with 3LISP, but Lisp has chosen to take the first road and
bite the QUOTE bullet.  It remains to be seen if Prolog will be able to
integrate more natural source to source transformations without going
the same route.

					--Barak.

∂28-Oct-85  1441	GJC@MIT-MC.ARPA
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  14:40:22 PST
Date: Mon, 28 Oct 85 17:41:39 EST
From: "George J. Carrette" <GJC@MIT-MC.ARPA>
To: JAR@MIT-MC.ARPA
cc: SCHEME@MIT-MC.ARPA
In-reply-to: Msg of Mon 28 Oct 85 15:27:44 EST from Jonathan A Rees <JAR at MIT-MC.ARPA>
Message-ID: <[MIT-MC.ARPA].695676.851028.GJC>

OK, Jonathon, here's my info message resent:

- Name of implementation: SIOD (Scheme In One Defun)
- Implemented by whom: GJC (George Carrette)
- Supported by whom, and to what extent: GJC, for use in LMI lisp classes.
- Hardware and operating system(s): LMI-LAMBDA, ZETA(FOO?)LISP.
- Availability: Given out at my "guest lectures" to LMI lisp classes.
- Description of dialect: Sufficient to run S&ICP problems I find
  most interesting. Especially streams, the meta-linguistic abtraction section,
  and the interpreter/hardware sections.
- Intended use: education. Both to introduce S&ICP and to show interpreter
  implementation, also "WHY MACROS OR BAD, or WHY CANT YOU READ MY CODE?"
- Implementation style: The function SEVAL (scheme EVAL) is one DEFUN.
  The "text" being interpreted is syntax-checked first, but is otherwise
  just the obvious s-expression. The environment representation is an ALIST.
  Because of the underlying simplicity it was possible to code
  special cases such as look-ahead for simple variable lookup,
  and primitives such as +,/,CAR,CDR, applied to simple variable lookups
  without fear. There is very little overhead in the interpreter besides
  variable lookup (a single instruction, %ASSQ) and environment consing,
  (cheaper by the dozen and with the volatility based GC). The resulting
  interpreter is somewhat gross because of its use of specialized
  macrology, but is extremely fast, especially when compiled into
  MICROCODE by the Microcompiler.
  
- Remarks: One reason for this was to see just how far a few hours work
on a simple idea implemented somewhat grossly could go. Whenever I was
too burned out to do design-level work or debugging work (presumably on
jobs that I was paid to do) I might feel like trying to code
another SIOD special case. It is also a study for "how much effort should
go into avoiding CONS, vs other things?" It could be interesting to
compare its efficiency with JAR's compiler-style CLSCH.

- Whom to contact for more information: GJC@MC.


∂28-Oct-85  1457	GJC@MIT-MC.ARPA 	moderation   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  14:57:48 PST
Date: Mon, 28 Oct 85 17:59:04 EST
From: "George J. Carrette" <GJC@MIT-MC.ARPA>
Subject:  moderation
To: narain@RAND-UNIX.ARPA
cc: SCHEME@MIT-MC.ARPA
In-reply-to: Msg of 28 Oct 85 10:24:25 PST (Mon) from Sanjai Narain <narain at rand-unix.ARPA>
Message-ID: <[MIT-MC.ARPA].695690.851028.GJC>

I think the problem was one of "oh no, not that again," for some of
the more experienced scheme/lisp hackers here. Even the most intense
personal discussions with participants such as Sussman, Hanson, etc.
never quite resolved some of these issues. There have been good
suggestions to solving the scoping problems of macros. 
Anyway, people dont seem willing to rehash the elementary arguments
again.


∂28-Oct-85  1542	@MIT-MC.ARPA:JINX@MIT-OZ 	moderation    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  15:42:40 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 28 OCT 85  17:41:02 EST
Date: 28 Oct 1985  17:40 EST (Mon)
Message-ID: <JINX.12154816414.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Sanjai Narain <narain@RAND-UNIX.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: moderation

There are 2 possible uses of macros:

- To provide SYNTACTIC EXTENSIONS to the language for convenience and
clarity.  This is the only legitimate use (as far as I'm concerned) of
a macro facility.  Examples of this are COND (in terms of IF) and LET
(in terms of LAMBDA).  Note that macros are needed for this case not
because of order of evaluation (the main difference, besides
assignment, between lambda calculus and Scheme), but rather because
the forms do not make sense as procedure applications.  For example,
consider

(let ((y (+ 2 3))) (* y y))

in a position where y is not bound.  If LET were a procedure, it would
receive 2 arguments ((y (+ 2 3))) and (* y y).  But then y would be a
free variable in the above expression, irrelevant of the order of
evaluation, which is certainly not the desired effect.  To obtain the
desired effect, something like a macro would be needed even in a
system which more closely modelled the lambda calculus.  Thus there is
something to macros which normal order evaluation in the lambda
calculus does not provide.

When used this way they are mere re-write rules (even character level)
and evaluation plays no part in them.  The re-write can be seen as
happening before the program is evaluated, since these expressions
would have no reasonable meaning otherwise.  Back-quote and comma can
be seen as ways of specifying string substitution.

- To obtain the effects of normal order evaluation, locatives, or
fexprs in a simple applicative order system like Scheme.  Consider,
for example, the standard Lisp SETF macro (not the T version which
falls into the previous category).  This is however a MISUSE, as far
as I am concerned, and the desired effect should be obtained
otherwise.  I believe it is in this case that all of the problems
about order of evaluation, etc. arise, which is not too surprising,
since a tool is being used for something other than its real purpose.

Just because a tool can be abused, it does not mean that it is wrong
or that it is inherently broken if it does not work when it is used
for a purpose other than its intended one.

∂28-Oct-85  1627	@MIT-MC.ARPA:HAL@MIT-OZ 	quote
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  16:26:58 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 28 OCT 85  17:58:03 EST
Date: Mon, 28 Oct 1985  17:58 EST
Message-ID: <HAL.12154819603.BABYL@MIT-OZ>
From: HAL%MIT-OZ@MIT-MC.ARPA
To:   scheme@MIT-MC.ARPA
Subject: quote


This is a comment on Sanji Narain's response to Paul Hudak's response
to his remark about quote:

    The question I asked is not as trivial as it sounds to people who
    seem to have objected to it. It has to do with the necessity of quoting
    expressions, something which is absent from other systems such as Prolog.

    Hudak made the mysterious comment that Scheme/T doesn't need
    to quote either. Well, if you want to set x to the symbol a try typing
    (set x a). In Prolog you can do X=a quite legitimately. The problem
    is simply that in Lisps there is no way of distinguishing variables from
    constant symbols of the same name. So, you must use quote.

This is an important issue that is very much misunderstood.

Lisp chooses to blur the line between data structures that can be
manipulated, and expressions in the language itself.  The reason for
doing this is that it leads to increased programming power.  For
instance, one could make a pattern matcher in which various elements
of the patterns are simply (names of) Lisp procedures, thus leading to
ability to explicitly EVAL parts of the pattern.

If one wanted to give up this power, then one could choose essentially
any ad hoc way to distinguish expressions from data (e.g., one could
capitalize all identifiers, as does Prolog).  Thus, in Prolog, one can
unambiguously write X=a (as Narain points out) but one cannot
unambiguously write X=Y, if the intent of this is to assign to X a
constant (written as Y), which is later to be assembled into a data
structure that is to be later interpreted as a Prolog program with an
identifier named Y.

Of course, there is nothing to stop one from writing a Prolog
evaluator in Prolog (and there are good reasons for doing so) but then
the quotation problem (distinguishing expressions in the Prolog that
is performing the evaluation from expression in the Prolog that is
being evaluated) arises just as it does in Lisp.

This is not to say that Lisp's (or Scheme's) treatment of quote is the
last word in handling this problem.  See Brian Smith's thesis for an
alternative, and perhaps more consistent approach.

A couple of people have suggested to Sussman and me that we give up
using quote in our book, since it would make things easier for
students, and also make a simpler language from a theoretical point of
view.  Our opinion is that quote (hence the ability to mix data and
expressions) provides a real source of power that is intimately
related to Lisp's ability to serve as an implementation vehicle for
embedded languages and programming environments.  But we do make this
point in our book.

It would be nice to assemble a collection of good examples that use
quote in this way.

Note that the same issues underly the use of macros.  Contrary to what
Narain asserts, macro expansion is not just lambda reduction.  This is
true for SOME macros (like defining IF in terms of COND) but not true
for others (such as DO) where the elements of the from may not even be
syntactically valid Lisp (or Scheme) expressions.


∂28-Oct-85  1720	@MIT-MC.ARPA:SRIDHARAN@BBNG.ARPA 	Why quote? 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  17:19:42 PST
Received: from BBNG.ARPA by MIT-MC.ARPA 28 Oct 85 19:58:55 EST
Date: Mon 28 Oct 85 17:58:28-EST
From: SRIDHARAN@BBNG.ARPA
Subject: Why quote?
To: scheme@MIT-MC.ARPA

1. Prolog does not have evaluation of function terms in its semantics.
All terms are what a Lisper might say always quoted.  The counterpart
of the problem for Prolog is how to introduce evaluated terms.
Since it feasible to write term rewrite rules (albeit only directional ones)
some form of evaluation can be introduced, producing various degrees
of partial and lazy evaluation methods.  But, there would be questions
similar to that of quoting, on under what circumstances what terms
will be evaluated.

2. It is true but somewhat misleading to say that Lambda-calculus has no
quoting.
(a) pure Lambda-calculus has no data structures; one can simulate data
structures by using closures in much the same way a cons-cell is defined
(in A&S book but also many other places) by a closure that returns its
first or second argument.  If one wants not simulated data structures,
but a machine-dependent real data structures (or at least dependent upon
some architectural feature such as dereferencing of pointers), one has to
introduce quotation. 
(b) simulated data structures will also introduce the confusion of quoting,
(car (lambda () a)) will be an irreducible expression; Scheme will generate
an error.

3. In Lisp implementations, since functions are called by value, one needs
to resort to tricks to get call by expression/reference.  In most realistic
cases, the difference between these is one of efficiency.  If an operation 
can be done on the expression once and used many times, one perhaps wishes
to macro expand it or advise the compiler to do the processing once.
Since efficiency is a legitimate concern of programmers,
macros/quotes/compiling are in the game.

4. There is another mechanism besides macros one might use - partial
compilation or compile time calculation.  If an expression e contains
a subexpression s that one wishes to be evaluated, and its value used
in its place, quite a bit of optimization can be handled this way.
Especially for people trying to do knowledge-based programming (not only
in rules but inother forms as well) a good deal of knowledge-dependency
might be evaluated in once and for all - only if a compiler allows us
to use evaluate-once expressions.
-------

∂28-Oct-85  1816	@MIT-MC.ARPA:JINX@MIT-OZ 	quote    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 28 Oct 85  18:16:49 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 28 OCT 85  21:14:26 EST
Date: 28 Oct 1985  21:13 EST (Mon)
Message-ID: <JINX.12154855097.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   HAL%MIT-OZ@MIT-MC.ARPA
Cc:   scheme@MIT-MC.ARPA
Subject: quote
In-reply-to: Msg of 28 Oct 1985  17:58-EST from HAL

I don't understand why people object to quote and not to double-quote.
For me the identifier (variable name) FOO and 'FOO are two distinct
objects which have no relation except potential similarity in printed
form (like "FOO" when display is used).  It is EVAL that is funny, in
the same way that linkers for all operating systems are funny in that
they transform what was previously considered passive data into active
data or programs.

∂29-Oct-85  0816	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	Re: need for quoting in Lisp
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Oct 85  08:16:01 PST
Received: from GODOT.THINK.COM by MIT-MC.ARPA 29 Oct 85 10:58:57 EST
Received: from polycarp by GODOT.THINK.COM via CHAOS; Tue, 29 Oct 85 10:59:07 est
Date: Tue, 29 Oct 85 11:00 EST
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: Re: need for quoting in Lisp
To: Barak.Pearlmutter@G.CS.CMU.EDU, scheme@MIT-MC.ARPA
Cc: gls@THINK-AQUINAS.ARPA
In-Reply-To: <499381673/bap@G.CS.CMU.EDU>
Message-Id: <851029110027.1.GLS@THINK-POLYCARP.ARPA>

    Date: 28 Oct 1985 16:07-EST 
    From: Barak.Pearlmutter@G.CS.CMU.EDU
								   ... To
    illustrate very concretely, imagine a Schemelike language which is NOT
    it's own metalanguage, in which there are no macros.  For any
    construct, we can tell unambiguously whether we have code or data
    in our hands, and hence quoting will be unnecessary.

    ...

To Mr. Pearlmutter's excellent exposition I would like to add the observation
that, 25 years ago, LISP was originally conceived in exactly these terms.
Allow me to add to the table of examples the representation as LISP
"M-expressions" ("meta-expressions"):

	    Regular Scheme				Scheme0			M-expressions

     (car (append x y))			(car (append x y))		car[append[x; y]]

     (car (quote (append x y)))		(car [APPEND X Y])		car[(APPEND X Y)]

     (append (f x) (g (quote y))	(append (f x) (g Y) [H Z])	append[f[x]; g[Y]; (H Z)]
	     (quote (h z)))


--Guy

∂29-Oct-85  0842	JAR@MIT-MC.ARPA 	administrivia
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Oct 85  08:42:46 PST
Date: Tue, 29 Oct 85 11:44:06 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  administrivia
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].696740.851029.JAR>

At least one person was confused about this, so I'll reiterate just to
make sure this is clear.

This list is not moderated.  If you send mail to SCHEME@MIT-MC you're
sending a message out to about 150 people.  Some of these people would
like to receive only pithy and extremely interesting messages.  If you
have any doubt about the appropriateness of a message, send it to
SCHEME-REQUEST@MIT-MC and it will be moderated, forwarded, answered,
edited, critiqued, ignored, or subjected to some combination of the
the above.  Thanks.

Actually I think it's been going pretty well, but I'd like to hear more
about the following: (a) implementations and (b) pedagogy.

∂29-Oct-85  1231	@MIT-MC.ARPA:cpd@LOCUS.UCLA.EDU 	Continuations    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 29 Oct 85  12:31:09 PST
Received: from LOCUS.UCLA.EDU by MIT-MC.ARPA 29 Oct 85 15:32:05 EST
Date:           Tue, 29 Oct 85 12:11:06 PST
From:           Charles Dolan <cpd@LOCUS.UCLA.EDU>
To:             scheme@mit-mc.arpa
Subject:        Continuations
Message-ID:     <499464666-2399-cpd@ZEUS.LOCUS.UCLA.EDU>

At UCLA we use T which does not support continuations.  I was wondering what
I am missing.  What are people out there using continuations for?  Do you
have simple examples which demonstrate how continuations make you solution
more elegant, efficient, ...?

-Charlie Dolan


∂30-Oct-85  0750	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: moderation 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  07:50:14 PST
Received: from yale by MIT-MC.ARPA 30 Oct 85 10:36:44 EST
Received: by Yale-Bulldog.YALE.ARPA; 30 Oct 85 09:59:36 EST (Wed)
Message-Id: <8510301459.AA07860@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Wed, 30 Oct 85 09:51:03 EST
Subject: Re: moderation
Date: Wed, 30 Oct 85 09:51:05 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Sanjai Narain <narain@RAND-UNIX>
Cc: scheme@MIT-MC
In-Reply-To: Sanjai Narain <narain@rand-unix.ARPA>, 28 Oct 85 10:24:25 PST (Mon)

    Hudak made the mysterious comment that Scheme/T doesn't need to
    quote either. ...

Sorry to sound mysterious.  My intent was to point out, as others
have by now, that quoting wasn't *necessary*, just as it isn't in
the lambda calculus; it is simply convenient, as most meta-tools are.

So it seems to me that the only issue is that if one decides to have
a "meta-language," how should it be manifested -- perhaps that's what
you were refering to.  Lisp chose quote, Prolog has a different
mechanism, Barak's "Scheme0" uses yet another.  I suppose they all
have their advantages/disadvantages.

I should clarify one other aspect of my "mysterious" comment:  QUOTE
is really just a way to create a data structure, and thus is not much
different from using, say, strings.  However, it's combination with
EVAL is what makes me shy away from macros.  It's usually the case
that if one is using QUOTE plus EVAL, there's a "cleaner" way to do
it with closures.

    -Paul

P.S. I agree with you that these discussions are OK for this
     mailing-list, but then again I'm not a Scheme expert who has
     perhaps hashed through these issues a hundred times before.

∂30-Oct-85  0909	@MIT-MC.ARPA:cpd@LOCUS.UCLA.EDU 	Re: Continuations
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  09:09:32 PST
Received: from LOCUS.UCLA.EDU by MIT-MC.ARPA 30 Oct 85 11:43:50 EST
Date:           Wed, 30 Oct 85 08:37:27 PST
From:           Charles Dolan <cpd@LOCUS.UCLA.EDU>
To:             Jim Meehan <Meehan@YALE.ARPA>
CC:             scheme@mit-mc.arpa
Subject:        Re: Continuations
In-reply-to:    Message of Tue, 29 Oct 85 16:15:37 EST
                    from "Jim Meehan <Meehan@YALE.ARPA>"
                    <8510292121.AA02629@Yale-Bulldog.YALE.ARPA>
Message-ID:     <499538247-20492-cpd@HERA.LOCUS.UCLA.EDU>


      Heresy!  Internally, T uses continuations all the  time  (surely
      you've seen these  while  crawling  through  the  stack with DEBUG).
      Users can also write them either by passing  LAMBDAs  or  by  using
      CATCH  (which is even  implemented as CALL-WITH-CONTINUATION).  The
      current T compiler doesn't take as much advantage of them as the
      prototype T  3.0  compiler does.  In  terms  of  running Lisp code,
      continuations are important for eliminating tail-recursion, etc.  Take
      a  peek  at  Abelson  &  Sussman, "Sturcture and  Interpretation  of
      Computer Programs."  But for general programming, passing
      continuations is  very  useful,  particularly  when you pass  more
      than  one;  each  indicates "what to do next" (i.e., how to continue
      the computation) in some particular  case,  which  can  lead to code
      that's  much  more  elegant than code that returns flags to the
      caller, or worse, multiple flags.  Continuations are  described  in
      the first   edition   of  Charniak,  Riesbeck,  and  McDermott,
      "Artificial Intelligence Programming," (Chapter 17,  I  think).   That
      section  has been  rewritten  in  the  new  edition  (which  Chris and
      I are just now finishing).

T does indeed use continuations internally and you can make them yourself
with LAMBDA expressions. In fact I do just that when compile TLOG (logic
programming) into T.  What T does not support is just the type of
continuations decribed in AI Programming, the kind that let you return to a
previous state of the computation.  Doing it with LAMBDAs is not as nice,
and its supported in COMMON LISP.

	You might  also  want  to read the "LAMBDA papers," a collection of
	tech reports from MIT written by Steele and Sussman in the days
	when  Scheme was still  being invented.  Steele's thesis also gives
	a pretty thorough description of the  continuation-passing  style
	(CPS),  e.g.,  how  any Lisp program  can  be  transformed  into
	CPS, which permits all sorts of optimizations.  "Returning"  a
	value  means  calling  the  continuation with that  value  as an
	argument.  The reason multiple-values (in Common Lisp) are
	semantically nice is that  they  can  (should)  be  viewed  as a
	notation/mechanism   for   calling  the  continuation  with  several
	arguements, not just one.

Thanks for the pointers.


∂30-Oct-85  1206	@MIT-MC.ARPA:JINX@MIT-OZ 	Continuations 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  12:05:44 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 30 OCT 85  14:03:53 EST
Date: 30 Oct 1985  14:02 EST (Wed)
Message-ID: <JINX.12155301033.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Charles Dolan <cpd@LOCUS.UCLA.EDU>
Cc:   Jim Meehan <Meehan@YALE.ARPA>, scheme@MIT-MC.ARPA
Subject: Continuations
In-reply-to: Msg of 30 Oct 1985  11:37-EST from Charles Dolan <cpd at LOCUS.UCLA.EDU>

Unfortunately, I think that Common Lisp style multiple-values provide
something which cannot be conveniently obtained with explicit
continuation passing.

Consider the problem of writting a mapping procedure, MVMAP, like MAP
(previously MAPCAR) with the constraint that (MVMAP f . lists) return
as many lists of values as f returns values (assuming that f returns
the same number of values on every invocation).  Then (MAP f . lists)
is equivalent to (MVMAP f . lists) if f returns a single value.

The problem writting it in continuation passing style is that f must
expect a continuation given to it by MVMAP, but then +, for example,
cannot be used since it does not expect an explicit continuation.
I agree that this can be "patched" by doing something like

(mvmap explicit->implicit (implicit->explicit +) . lists)

where EXPLICIT->IMPLICIT is the explicit continuation to MVMAP, used
to pass on the "return" value to the implicit continuation, and is defined by

(define (explicit->implicit val) val)	; Gives error if more than one value

and IMPLICIT->EXPLICIT makes a procedure, which only expects an
implicit continuation, accept an explicit continuation:

(define (implicit->explicit f)
  (lambda (cont . args)
    (cont (apply f args))))

but this is somewhat clumsy, especially if MVMAP were to replace MAP,
as it probably should if it were implemented.

The problem arises because in Common Lisp returning one value is not
much different from returning several, since almost all of the burden
is put on the "receiving" end (and, of course, in VALUES).  By
implementing multiple values in terms of explicit continuation
passing, we make procedures which potentially "return" multiple values
(even if they happen to always "return" one) quite different from
"normal" procedures since these do not expect an explicit
continuation.

∂30-Oct-85  1351	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	will the real current continuation please stand up
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  13:50:24 PST
Received: from yale by MIT-MC.ARPA 30 Oct 85 16:45:38 EST
Received: by Yale-Bulldog.YALE.ARPA; 30 Oct 85 15:33:19 EST (Wed)
Message-Id: <8510302033.AA12517@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Wed, 30 Oct 85 15:35:25 EST
Subject: will the real current continuation please stand up
Date: Wed, 30 Oct 85 15:35:29 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: scheme@MIT-MC
Cc: 

I have a question for the Scheme philosophers, which relates somewhat
to pedagogy:  Why was CALL/CC designed in just the way it was?  In
particular, I tend to think of CALL/CC as "providing a way to grab
the current continuation," which makes especially good sense to those
familar with denotational semantics.  But then the immediate question
raised is, "why not just have a procedure CURRENT-CONTINUATION that,
when called with no arguments, returns the current continuation?"
The answer, of course, is that then no real "fork" in the processing
occurs, which brings up the following point:  In a sense CALL/CC does
*not* pass the current continuation to its argument; it passes the
continuation corresponding to the point *surrounding* the call to
CALL/CC.  The *real* current continuation is the one that passes control
to the functional argument to CALL/CC.

So my question is this:  Has anyone considered alternate ways of
providing the CALL/CC capability?  And does it make any sense at all
to use something like the CURRENT-CONTINUATION suggested above?
(I am *almost* convinced that I can't implement CALL/CC with
CURRENT-CONTINUATION, but maybe I haven't thought hard enough.)

    -Paul

∂30-Oct-85  1410	JAR@MIT-MC.ARPA 	Continuations
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  14:09:59 PST
Date: Wed, 30 Oct 85 17:10:56 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Continuations
To: Meehan@YALE.ARPA
cc: SCHEME@MIT-MC.ARPA, cpd@LOCUS.UCLA.EDU
In-reply-to: Msg of Wed 30 Oct 85 08:37:27 PST from Charles Dolan <cpd at LOCUS.UCLA.EDU>
Message-ID: <[MIT-MC.ARPA].698607.851030.JAR>

Let's not quibble over terminology.  CPD's question is perfectly clear
and well-informed.  T supports continuations like Fortran does: they
exist but aren't first-class; they can't be returned as values of
procedures.  I think that when talking about continuations it's OK to
omit the qualifier "first-class," since it's usually understood, the
same way it's understood when you say "closure."  It's vacuous to say
that a language has or doesn't have closures or continuations unless the
adjective first-class is assumed; therefore assume it.  (Some people
will always choose to be confused.)

I think first-class continuations are generally good for the soul, and I
think it's good that the new Scheme report requires them.  I've never
claimed that T was really a Scheme dialect.  (Maybe one of these days it
will be.)  But the question of what one legitimately does with
continuations is nontrivial.  I'd like for people out there who have
real experience with them (e.g. someone from Indiana) to say something
about this.

The main problem I have with continuations is that a truly correct
implementation would dictate that a compiler cannot beta-convert in many
places where beta-conversion would otherwise be desirable.  This problem
is discussed on page 92 of Steele's tech report on RABBIT.

∂30-Oct-85  1503	JAR@MIT-MC.ARPA 	will the real current continuation please stand up   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  15:02:08 PST
Date: Wed, 30 Oct 85 18:02:44 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  will the real current continuation please stand up
To: Hudak@YALE.ARPA
cc: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].698732.851030.JAR>

I think they're equipotent, if you allow a little bit of kludgery.

I take it you would define
    (current-continuation)
to mean the same as
    (call-with-current-continuation (lambda (c) c))  ?

Then e.g.
    (let ((c (current-continuation)))
      (cond ((eq? c 'a) 'b)
	    (else (c 'a))))
would evaluate to b.

Then I think you could just do this:

(define (call-with-current-continuation p)
  (let ((c (current-continuation)))
    (cond ((pair? c)
	   (car c))
	  (else
	   (p (lambda (val) (c (cons val nil))))))))

I think it's somewhat more natural to take
call-with-current-continuation as primitive.

∂30-Oct-85  1800	@MIT-MC.ARPA:JINX@MIT-OZ 	will the real current continuation please stand up    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  17:55:13 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 30 OCT 85  20:33:57 EST
Date: 30 Oct 1985  20:32 EST (Wed)
Message-ID: <JINX.12155372006.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Jonathan A Rees <JAR@MIT-MC.ARPA>
Cc:   Hudak@YALE.ARPA, SCHEME@MIT-MC.ARPA
Subject: will the real current continuation please stand up
In-reply-to: Msg of 30 Oct 1985  18:02-EST from Jonathan A Rees <JAR at MIT-MC.ARPA>

The main difference that I see between CALL-WITH-CURRENT-CONTINUATION
and CURRENT-CONTINUATION is that when CURRENT-CONTINUATION is used,
the continuation returned has already been invoked (namely to return
itself), thus any further (explicit) invocations are additional
invocations.  In the CALL-WITH-CURRENT-CONTINUATION world this
continuation has not yet been "used".  While there is no difference if
continuations are re-entrant (they can be invoked more than once),
CURRENT-CONTINUATION can only be used under this assumption.

As far as HUDAK@YALE's original question: He distinguished between the
continuation to the CALL-WITH-CURRENT-CONTINUATION invocation (outer
continuation), and the continuation to the argument (inner
continuation), but the way I see it both are the same.  The
continuation-passing definition of CALL-WITH-CURRENT-CONTINUATION that
I use is:

(define (call-with-current-continuation *cont* receiver)
  (receiver *cont* *cont*))

where procedures always receive an additional argument (the first)
which is the implicit continuation.  Clearly then both continuations
(outer and inner) are the same.  In other words, since
CALL-WITH-CURRENT-CONTINUATION reduces (tail-recurses) into its
argument, the continuations are the same.

∂30-Oct-85  1827	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: will the real current continuation please stand up 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 30 Oct 85  18:27:15 PST
Received: from yale by MIT-MC.ARPA 30 Oct 85 21:25:22 EST
Received: by Yale-Bulldog.YALE.ARPA; 30 Oct 85 21:12:27 EST (Wed)
Message-Id: <8510310212.AA00384@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Wed, 30 Oct 85 20:40:10 EST
Subject: Re: will the real current continuation please stand up
Date: Wed, 30 Oct 85 20:40:11 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Jonathan A Rees <JAR@MIT-MC>
Cc: SCHEME@MIT-MC
In-Reply-To: Jonathan A Rees <JAR@MIT-MC.ARPA>, Wed, 30 Oct 85 18:02:44 EST

    I think they're equipotent, if you allow a little bit of kludgery.
    ...
    
Very nice -- although I'd call it "cleverness" rather than "kludgery."

    I think it's somewhat more natural to take
    call-with-current-continuation as primitive.
    
I can't argue with that.  But it's satisfying to know that
call-with-current-continuation can be implemented with something that
in a sense is more primitive.  Thanks.

        -Paul

∂31-Oct-85  1024	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Scheme Implementation Blurb:  Chez Scheme
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 31 Oct 85  10:24:31 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 31 Oct 85 13:21:54 EST
Received: from indiana by csnet-relay.csnet id ac00927; 31 Oct 85 13:18 EST
Date: Thu, 31 Oct 85 11:27:02 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: SCHEME@mit-mc.ARPA
Subject: Scheme Implementation Blurb:  Chez Scheme

Implementation:     Chez Scheme
Authored by:        Kent Dybvig
Supported by:       limited support by the author
Hardware:           VAX
Operating Systems:  4.2 BSD UNIX (or ULTRIX)
Implementation:     incrementally compiled to native code
Intended Use:       education and research

Chez Scheme was first released earlier this year and is now
being used at about 10 universities for classes and research.
Chez Scheme supports almost all of the required and optional
features of the RRRS.  The next major release (in spring or
summer 1986) will support 100% of the required features of the
standard.

In addition to the features of the RRRS, Chez Scheme provides
error and exception handling, engines, programmable cafes and
waiters (fancy read-eval-print loops), tracing and statistics-
gathering facilities, and fast-loading compiled files.  Chez
Scheme provides floating point numbers, arbitrary-precision
ratios, and arbitrary-precision integers, but no imaginary
numbers at this time.

Bruce Smith of UNC and myself have written a book on Scheme
that is scheduled to be published in the spring.  This book
serves as the reference manual for Chez Scheme and is sent
in draft form with Chez Scheme distributions.

Chez Scheme's biggest claim to fame is the speed and size of
its implementation.  It outperforms Franz Lisp and DEC Common
Lisp on most programs, but the initial core image is less than
500K bytes, about half of which is read-only and sharable.

Sue Dybvig and myself have started a small consulting business,
named Cadence Research Systems, primarily for the purpose of
distributing and supporting Chez Scheme.  We charge a license
fee to cover costs of distribution.  The license fee per site
is $400 for US colleges and universities and $1000 for companies
who will use the system for research and education only.  

For the license forms and ordering information, contact:

   Kent Dybvig
   Cadence Research Systems
   620 Park Ridge Road
   Bloomington, IN  47401
   812/333-9269

You can also reach me during the day at 812/335-8653.


Kent Dybvig
dyb.indiana@csnet-relay


∂01-Nov-85  1351	@MIT-MC.ARPA:HUDAK@YALE.ARPA 	Re: will the real current continuation please stand up 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 1 Nov 85  13:51:41 PST
Received: from yale by MIT-MC.ARPA  1 Nov 85 16:50:27 EST
Received: by Yale-Bulldog.YALE.ARPA; 1 Nov 85 14:46:13 EST (Fri)
Message-Id: <8511011946.AA01493@Yale-Bulldog.YALE.ARPA>
Received: from YALE-RING by YALE-RES via CHAOS; Fri, 1 Nov 85 14:47:57 EST
Subject: Re: will the real current continuation please stand up
Date: Fri, 1 Nov 85 14:47:58 EST
From: Paul Hudak <Hudak@YALE.ARPA>
To: Bill Rozas <JINX%MIT-OZ@MIT-MC>
Cc: SCHEME@MIT-MC
In-Reply-To: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>, 30 Oct 1985  20:32 EST (Wed)

    As far as HUDAK@YALE's original question: He distinguished between
    the continuation to the CALL-WITH-CURRENT-CONTINUATION invocation
    (outer continuation), and the continuation to the argument (inner
    continuation), but the way I see it both are the same.  
    
I see your point.  I guess it all depends on how one defines
"continuation."  I was interpreting it as "what happens next," 
so in your definition:

    (define (call-with-current-continuation *cont* receiver)
      (receiver *cont* *cont*))

what happens next is a call to receiver, so the (eventual) call to
*cont* is "delayed."  On the other hand, in:

    (define (current-continuation *cont*)
      (*cont* *cont*))

the current continuation is called immediately (i.e., passed to itself),
which is of course what you pointed out in the first part of your message.

    -Paul

∂08-Nov-85  1809	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Syntactic extensions to Scheme   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 8 Nov 85  18:09:06 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA  8 Nov 85 12:49:59 EST
Received: from ti-csl by csnet-relay.csnet id ad09069; 8 Nov 85 12:44 EST
Date:  7 Nov 1985 1112-CST
From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: Syntactic extensions to Scheme
To: RRRS-Authors@mit-mc.arpa
cc: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
Received: from csl60 by ti-csl; Fri, 8 Nov 85 10:09 CST

One of the issues shunted aside a year ago was the question of how to
provide users with the ability to make syntactic extensions.  I think
it would be fruitful to have some calm discussion on this topic in the
RRRS-AUTHORS mailing list.  I doubt if we're ready to standardize on
any particular approach, but it would be helpful if we all knew more
about the alternatives and people's experiences with them.

I'm particularly interested in experiments such as T's with extensive
support for syntax tables.  What are their strengths and weaknesses?
What do they cost in terms of compiler or runtime complexity?  Do
users make effective use of them?  How flexible are they---would they
suffice for major language changes?

Should syntactic extensions be specified entirely in source terms, or
should the user have access to internal representations?  Should
simple source-to-source optimizations be communicated to the compiler
using the same mechanism, or is something else more appropriate?

Regards,
David Bartley
-------


∂12-Nov-85  1334	@MIT-MC.ARPA:OXLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	PC Scheme Implementation Information    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Nov 85  13:34:33 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 12 Nov 85 16:33:12 EST
Received: from ti-csl by csnet-relay.csnet id ae14406; 12 Nov 85 16:17 EST
Date: 12 Nov 1985 1035-CST
From: Don Oxley <OXLEY%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: PC Scheme Implementation Information
To: Scheme@mit-mc.arpa
Received: from csl60 by ti-csl; Tue, 12 Nov 85 12:48 CST

The following description of TI's PC Scheme product is a (belated)
response to Jonathan's request for implementation information:


Implementation:     PC Scheme
Developed by:       Texas Instruments Computer Science Lab
Supported by:       Texas Instruments Digital Systems Group
Hardware:           TI Professional and TI Business-Pro Computers,
                    IBM PC, PC/XT, PC/AT and IBM compatibles
Operating Systems:  MS(tm)-DOS 2.1 (PC-DOS) or better (at least 320K, dual
                        floppy)
Price/Availability: List price - $95, available in December 1985
Implementation:     Incrementally compiled to byte-codes
Intended Use:       Education, research, and support of AI software on PCs

PC Scheme is an implementation of Scheme for the TI Professional
Computer and IBM(r) Personal Computer families.  The product
consists of an optimizing compiler, a byte-code interpreter, extensive
run time support, an interactive, display-oriented editor, a language
reference manual, and a user's guide.  The system was developed on the
TI Professional Computer in Scheme itself, with critical run time
routines coded in C and assembly language for increased performance.

PC Scheme provides all the essential and most of the optional features
of the Revised Revised Report on Scheme.  It fully supports the
dialect used in the book "Structure and Interpretation of Computer
Programs" by Abelson and Sussman as well as many extensions developed
at Indiana University, MIT, and TI.  These include first-class engines
and environments and an experimental, object-oriented programming
system with dynamic multiple inheritance called SCOOPS.  Data type
support includes symbols, lists, vectors, strings, fixnums, bignums,
flonums (64 bit IEEE floating point), characters, closures,
continuations, environments, and I/O ports.

Evaluation is based on incremental compilation to byte-coded "virtual
machine" code which is emulated using threaded code techniques.
Informal benchmarks, including some of the Gabriel set, show PC Scheme
programs to be about 3-10 times faster than interpreted IQLISP(tm) and
2-4 times faster than interpreted Golden Common LISP(tm).

PC Scheme is oriented primarily towards compilation and fast execution
rather than extensive source-level debugging.  However, it does
provide trace and breakpoint facilities and an interactive Inspector
with commands to display and manipulate call stack frames and lexical
environments, edit variable bindings, trace back through a chain of
procedure calls, and evaluate expressions in the environment of a
breakpoint.  All user-correctable errors trap to the Inspector.

The display-oriented editor supplied with PC Scheme is a subset of
EDWIN, a version of EMACS written by the Scheme project at MIT and
adapted to PC Scheme by TI.  512K bytes of RAM are required to use
EDWIN.

Other PC Scheme run time support includes windowed screen input/output,
graphics, a pretty-printer, and an editor of in-memory list structures.
Compiled files can be converted to a "fast-load" format to speed up load
times.  Files containing variable definitions can be "autoloaded" on
demand.  A Winchester disk minimizes the inconvenience of autoloading,
but is not required.

Documentation includes a 286-page language reference manual and a
93-page user's guide.  Neither manual attempts to be a tutorial manual
for Scheme itself.

PC Scheme is being used extensively within Texas Instruments and is
the basis for future releases of TI's PC-based AI products, including
Arborist (tm) and the Personal Consultant Plus (tm).  It is currently
in use at approximately 25 universities in various settings (classes,
experimentation, evaluation).

PC Scheme may be ordered beginning November 15 for shipment in
December.  To order, write to Texas Instruments, 12501 Research Blvd.,
MS 2151, Austin, TX 78759 and ask for TI Part number #2537900-0001.
You may also order by telephone using MasterCard or VISA by calling
1-(800)-TI-PARTS.

Questions or comments on the product may be directed to the address
given above.  We also welcome less formal technical questions and
comments, which may be directed via CSNET to Oxley@TI-CSL.


        --Don

-------


∂12-Nov-85  1905	JAR@MIT-MC.ARPA 	test message 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Nov 85  19:05:00 PST
Date: Tue, 12 Nov 85 22:04:47 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  test message
To: RRRS-AUTHORS@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].716206.851112.JAR>

Please ignore.

(I want to make sure that sending to this list actually works.)

∂13-Nov-85  1618	JAR@MIT-MC.ARPA 	a modest backquote proposal 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Nov 85  16:11:54 PST
Date: Wed, 13 Nov 85 19:13:47 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  a modest backquote proposal
To: RRRS-AUTHORS@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].716925.851113.JAR>

I would like to propose the following: we should agree on a standard
internal form for backquote forms.  That is, if a portable Scheme
program does (READ) and the available input is e.g. "`(FOO ,BAR (A ,@BAZ
B))", or if the expression '`(FOO ...) occurs in the program itself, the
program should be able to detect the fact that it has its hands on a
backquoted form, and take it apart and do something meaningful with it.
I would like the situation to be exactly the same as that of the 'FOO
syntax, where we know e.g. that (CAR ''FOO) => QUOTE and (CADR
''FOO) => FOO.

Just to make this concrete, here is one form that this proposal could
take: we could say that '`(FOO ,BAR (A ,@BAZ B)) is semantically
identical to '(#!QUASIQUOTE (#!UNQUOTE BAR) (A (#!SPLICE BAZ) B)).  We
need not specify what the objects #!QUASIQUOTE etc. are; they could be
symbols or special constants.  All that's needed is e.g. that (EQ?
'#!UNQUOTE '#!UNQUOTE) will work, that is, you get an EQ object each
time you read that syntax - the same situation as with symbols.

Thus we would have:  (CAADR '`(FOO ,BAR)) => #!UNQUOTE, and so on.

Note that this implies nothing about implementation except that the
"expansion" of backquote forms into calls to LIST etc., if indeed that's
how it's done, isn't generally done at "read time," but rather at
"compile time" or "macro expansion time".  (Expansion at read time would
of course be correct if the file was being read by LOAD and the
backquote form was known to occur outside of a QUOTE special form, etc.
All that's important is behavior detectable by user code.)  We would
just need to add #!QUASIQUOTE as a new special form or macro.  I know
that this would be a trivial change to MIT Scheme and T, for example,
since they already work this way.

Now here's the rationale:

(1) This removes a wart in the meaning of READ and QUOTE.  Without this,
there is absolutely nothing in the report which guarantees that reading
or quoting backquote forms is even legal, much less that it has a
predictable meaning.  But the absence of a representation for backquote
forms is the only obstacle to this.  Given such a representation, we
have a very nice general syntactic property: any sequence of terminals
which may be derived from the the <expression> nonterminal may also be
derived from the <datum> terminal.  That is, READ and QUOTE give
standard representations of programs as data.

(2) As a consequence, it will be possible to write portable
interpreters, compilers, cross-compilers, macroexpanders,
cross-reference programs, pretty-printers, readers, and so forth, which
will work on any program written in RRRSS, even those that use
backquote.

It seems to me that the desirability of being able to write
meta-programs would far outweigh any arguments about implementation
preemption.  I guess I might be asking some of you to modify your
implementations (e.g. some implementations might be expanding at read
time), so there's a tiny bit of work involved in this, but I think it
would generally be a very easy change for most implementors to make.
(By the way, there is a subtlety involved in expanding nested backquote
forms AFTER read time which I'll explain under separate cover if someone
asks me to.)

The fact that Common Lisp doesn't have this feature has made it
difficult to write a portable implementation of RRRSS in Common Lisp.
To do it right I'll have to define my own backquote read macro and
expander, which is silly of course.  The situation is worse in Scheme,
which doesn't have read macros - one would actually have to write a
reader in order to write any portable meta-program.

[Unrelated footnote: LOAD and EVAL are equipotent; either can be
implemented in terms of the other.  RRRS has one but not the other.]

∂14-Nov-85  1020	JAR@MIT-MC.ARPA 	Syntactic extensions to Scheme   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Nov 85  10:17:09 PST
Date: Thu, 14 Nov 85 13:19:18 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Syntactic extensions to Scheme
To: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of 7 Nov 1985 1112-CST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].717960.851114.JAR>

    Date: 7 Nov 1985 1112-CST
    From: David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

    ... I'm particularly interested in experiments such as T's with extensive
    support for syntax tables.

You ask hard questions.  Therefore this message is very long.

Before answering the questions, I'll summarize how T syntax tables work:

The evaluator and compiler each take a syntax table argument.  A syntax
table maps symbols to objects called "syntax descriptors".  A syntax
descriptor is basically either a primitive token, for primitive special
forms like QUOTE and LAMBDA, or it's a macro expansion function.  Syntax
descriptors print as #[Syntax ...], where ... somehow identifies the
descriptor (name or whatever).

When the compiler processes a form whose car is a symbol, the first
thing it does is look up the symbol in the syntax table.  If there is an
entry in the table, say (syntax-table-entry table 'foo) => #[Syntax
BAR], the form is processed as if the form (#[Syntax BAR] ...) had been
seen.  When a form whose car is a syntax descriptor is processed, the
appropriate thing happens; if the descriptor is a macro expander, the
form is expanded; if it's primitive, the form is interpreted as a QUOTE
or LAMBDA or whatever expression.

Users can create syntax tables, fetch and store entries in them, and
pass them to the evaluator or compiler.  A macro (macro-expander ...)
creates a descriptor for a macro expander.  If no syntax table argument
is supplied to EVAL or LOAD, a syntax table is obtained from the
environment argument by accessing the value of a lexical environment
variable with a special internal name (let's suppose the name is
&&syntax-table&&; in principle it's something untypable).  There is
a special form DEFINE-SYNTAX which basically does a RUNTIME side-effect
of storing a descriptor into &&syntax-table&&.  (DEFINE-SYNTAX has
no effect at compile time.)

In addition, DEFINE-LOCAL-SYNTAX defines a macro local to a file or
expression, analogous to MACROLET in Common Lisp.  This has no effect at
runtime.  (DEFINE-MACRO (FOO ...) ...) is a horrible dual-purpose form
which is the same as
  (BEGIN (DEFINE-SYNTAX (FOO ...) ...)
	 (DEFINE-LOCAL-SYNTAX (FOO ...) ...)).

End of summary, now for the questions.

    What are their strengths and weaknesses?

Strength: the ability to make "absolute references" to standard syntactic
forms - i.e. (#[Syntax LAMBDA] (X) (+ X 5)) - is a boon to embedded
incompatible language implementation.  E.g. suppose you wanted to define
a syntax table where DEFINE was a macro which expanded into something
which wanted to use the usual Scheme DEFINE.  It wouldn't work to do
  (define-syntax (define ...) `( ... (define ...) ...))
since this is circular.  But you could do
  (define-syntax (define ...) `( ... (#[Syntax DEFINE] ...) ...))
where #[Syntax DEFINE] denotes the standard syntax descriptor for
DEFINE.

This is how I was able to write implementations of RRRSS and even a sort
of bastard Common Lisp in T, even though there were multiple
incompatibilities.  And because everything is scoped, one environment's
macros aren't seen in different environments, so one can easily debug
programs different parts of which are written using completely
different syntax.

The standard system macros all do the absolute reference trick, and the
effect is that a macro can expand a form into a new form which uses a
different macro, without having to worry about whether the macro in the
expansion was defined in the syntax table being used to process the
expansion.  Thus descriptors can be moved from one syntax table to
another without worrying too much about how they're defined - they act
almost like closures.  (Note that this problem doesn't come up in Common
Lisp because one "closes" over an environment (package) at read time.
Macros in Scheme have to be more complicated since Scheme did the right
thing with symbols.)

Weaknesses: there are the usual kinks.  Best to give an illustration.
Suppose a Scheme program (file) contains the following forms:

    (define-macro (foo form) (bar form))

    (define (bar form) `(#[syntax lambda] () (baz ,form)))

    (define (baz obj) (cons (cdr obj) (car obj)))

    ((foo (cons 'a 'b)))

If your model of macro expansion is that it's part of what the evaluator
does, then this "works:" the last form evaluates to (b . a).  This is
the simplest explanation of what macos do, and it's what I think most
naive users believe happens.  Indeed it is what happens in many Lisp
interpreters.

However, the code is obviously sensitive to what happens at compile time
and what happens at run time.  Presumably the compiler does not load the
file.  So when the FOO form gets expanded by the file compiler, the
expander tries to call BAR, which is undefined.

T is badly engineered in the sense that this code will run interpreted
and not compiled.  This is because the environment in which the macro
expansion function is closed is the same as the one in which the
expansion will run.  (Common Lisp has the same problem.)  Users should
have to work much harder than this to find inconsistencies like this.  A
small improvement would be if LOAD "macroexpanded" the whole file before
running any of it; then FOO would be undefined at expand time.  But this
isn't a very general solution.  What if the forms occur in different
files?  What if the code is reloaded into the same environment - will it
work the second time, using the definition of FOO from the first LOAD?

In the best of all possible worlds, macros and the auxiliary functions
they call to perform expansions should only have to exist for the
purposes of compilation (and EVAL, debugging, etc.); at runtime they can
go away or be garbage collected.  (Consider using a Scheme compiler to
build a small stand-alone system which wants to run in minimal address
space.  Expansion functions are superfluous at runtime.)  This suggests
that macros should always inhabit separate modules in their own separate
environments.  These modules can be loaded for compilation purposes, if
a client requests, but needen't exist at runtime.  Users should have to
go to the extra trouble of announcing that they are defining a
compilation-support module to cause DEFINE-SYNTAX itself to become
available at all.

I haven't even talked about the problem of the scoping of BAZ.  As it
is, any client of the FOO macro must know that the variable BAZ occurs
free in the expanded form, and suffer the consequences.  I don't see any
way around this if out-of-core compilation is going to work.  A listing
of what variables are free (in principle one needs at most 1 such) must
simply be part of the documentation of FOO.  (One can play tricks with
system primitives like CAR, but the problem remains when the expansion
needs a user-defined function.)

Whew...  obviously this is much too complicated.  I have sympathies for
the trstricted Indiana approach to macros, although I'm not sure it gets
around all the various problems, and I would resist giving up the
ability to write arbitrary expansion procedures.  But I am certainly not
asking anyone to adopt T's syntax mechanism, since the specification is
so bug-ridden.

    What do they cost in terms of compiler or runtime complexity?

In spite of all this wind, the implementation is very straightforward.
One just puts hooks into EVAL and the compiler in the right place, and
passes the syntax tables around as appropriate.

    Do users make effective use of them?

As long as macros exist, users will abuse them.  But I think they have
their place, and a small number of people know how to use them well.  It
has been suggested that a licensing agency be established.

As far as syntax tables go, I don't know of anyone who has done anything
with them quite as hairy as what I've described, but I think that the
people who exploit multiple environments (there aren't many) implicitly
use the fact that macros get scoped appropriately; they know there won't
be name conflicts, the same way they know that there won't be name
conflicts for variables.

    How flexible are they---would they suffice for major language changes?

I think what I said above about embedded languages answers this for the
most part - in the affirmative.  Clearly they wouldn't be effective e.g.
to change scoping or evaluation order rules, but they work well
to change the meaning of (LAMBDA ...).

    Should syntactic extensions be specified entirely in source terms, or
    should the user have access to internal representations?

I have a running argument with the MIT Scheme folks about this; I think
that Scheme makes a perfectly good representation for programs.  There
are some scoping problems to be addressed, e.g.  any macro expander
which wants to understand anything about a subexpression must know what
syntax table the subexpression is to be interpreted relative to, but as
long as some convention is established (there are a couple of
alternatives) and programmers are made aware of these issues, I don't
think we need to go to the trouble of defining new data types for
representing programs.  That would be very complicated and there'd be
little hope of making the interface portable.

    Should simple source-to-source optimizations be communicated to the
    compiler using the same mechanism, or is something else more
    appropriate?

Definitely not.  I'm not sure that users should ever specify
optimizations to a compiler; perhaps it would be acceptable if the
compiler had some mechanism by which it could prove the correctness of
such transformations before deciding it was okay to do them.  Also, the
situation with free variables can be very complicated.  But in any case,
just for pedagogical reasons one shouldn't do anything to lead users to
believe that macros and procedures have any similarites at all.  It's
bad enough that they are syntactically similar.

[By the way, even though T and MIT Scheme agreed some years back that
(LET ((IF LIST)) (IF 1 2 3)) should evaluate to 2 , and I used to think
this was the only acceptable semantics, now I'm not convinced that
this is the right thing; I think Kent Pitman has a coherent semantics
which would allow it to evaluate to (1 2 3), without sacrificing
compilability or purity.  But I'll let him explain that.  I'm not
convinced he's right either.]

∂14-Nov-85  1559	@MIT-MC.ARPA:JINX@MIT-OZ 	Syntactic extensions to Scheme (long message)    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Nov 85  15:59:18 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 14 NOV 85  18:36:00 EST
Date: 14 Nov 1985  18:28 EST (Thu)
Message-ID: <JINX.12159281629.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Jonathan A Rees <JAR@MIT-MC.ARPA>
Cc:   Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA, RRRS-AUTHORS@MIT-MC.ARPA
Subject: Syntactic extensions to Scheme (long message)
In-reply-to: Msg of 14 Nov 1985  13:19-EST from Jonathan A Rees <JAR at MIT-MC.ARPA>


Just a few comments explaining a little about how syntax tables in MIT
Scheme currently work.

Scheme programs are translated into SCode (1) before either the evaluator
or the compiler touch them, thus macros do not have to be handled by
either but by this translator, which we call the syntaxer.

The syntaxer has one required argument (the expression to translate to
Scode), and two optional arguments.  One of them is the syntax table
to use in the translation.  The other is the syntax environment, which
is the environment in which to evaluate any expressions which must be
evaluated at syntax time, e.g. lambda expressions which result in
macro expanders.

If these arguments are not given explicitly, default values are used.
These default values can be manipulated with the procedures
current-syntax-table, set-current-syntax-table!, with-syntax-table,
and the analogous ones for syntax environments.

There are some operations defined on syntax tables:

(syntax-table-define <table> <symbol> <translator>)
(syntaxt-table-ref <table> <symbol>) -> <translator>

and some less interesting ones.

A translator is supposed to translate an s-expression into Scode, but
source to source macro facilities are also provided.  Some syntax time
syntactic sugar is also provided, thus

(define-syntax <name-of-special-form> <translator>)

Does a syntax-time syntax-table-define on the current syntax table,

(let-syntax ((<name> <translator>)...) . <expresssions>)

is analogous to LET, creating a new syntax table,

(using-syntax <syntax-table> . <expressions>)

is the syntax-time with-syntax-table, and

(macro <formals> . <body>)

is analogous to LAMBDA but "returns" a source level translator, similar
in effect to traditional Lisp Macros, except that they are expanded at
syntax time.

We do not provide "reader" syntax for obtaining translators or
denoting expansions, we instead invoke them explicitely to insure that
the correct expander is used.  Thus if WHILE is defined by

(define-syntax while
  (macro (pred . exps)
    `(let ((pred (lambda () ,pred))
	   (body (lambda () ,@exps)))
       (letrec ((loop
		 (lambda ()
		   (if (pred)
		       (begin (body) (loop))))))
	 (loop)))))

The following 2 definitions have different effects, depending on
whether WHILE is redefined

(define-syntax for
  (macro (index low high . exps)
    `(let ((,index ,low))
       (while (<= ,index ,high)		; Dynamic use of WHILE
	      ,@exps
	      (set! ,index (1+ ,index))))))

(define-syntax for
  (let ((while-xform			; The translator
	 (syntax-table-ref (current-syntax-table) 'WHILE)))
    (macro (index low high . exps)
      `(let ((,index ,low))
	 ,(while-xform			; Static use
	   `(while (<= ,index ,high)
		   ,@exps
		   (set! ,index (1+ ,index))))))))

Note that the traditional Lisp DEFMACRO can be obtained by

(define-syntax defmacro
  (macro (pattern . body)
    (let ((the-name (car pattern))
	  (the-translator `(macro ,(cdr pattern) ,@body)))
      `(begin
	(syntax-table-define (current-syntax-table)	; Runtime
			     ',the-name
			     ,the-translator)
	(define-syntax ,the-name ,the-translator)))))	; Syntax (compile) time

In the example that Jonathan gives we would also have problems, since
the default is that the current syntax environment is the same as the
read-eval-print loop environment, thus the code would "work"
interpreted but not compiled.  Changing current syntax environment is
a possibility which we should probably do.

We do not object to using Scheme for syntactic extensions.  As a
matter of fact, I never write syntactic expressions which do not end
up being macros (after grabbing the appropriate stuff), only the
bottom level (the core special forms) translate to Scode, but there is
no reason not to make this an option in our system.

I agree with Jonathan in that syntax should not be used for
optimizations, and also in that lambda-bound names should take
precedence over syntactic items.  Thus in his binding-of-IF example, I
think that '(1 2 3) should be returned.  We probably will change our
system to do this, but we have not yet done that.


(1) Scode can be thought of as a small, explicit version of Scheme,
where every expression is an explicit special form, thus it has
VARIABLE and COMBINATION explicit special forms.


∂14-Nov-85  2150	@MIT-MC.ARPA:CPH@MIT-OZ 	Syntactic extensions to Scheme
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Nov 85  21:50:40 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 15 NOV 85  00:41:14 EST
Date: Fri, 15 Nov 1985  00:37 EST
Message-ID: <CPH.12159348700.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Jinx%MIT-OZ@MIT-MC.ARPA
Cc:   JAR@MIT-MC.ARPA, Bartley%CSL60%TI-CSL.CSNet@CSNET-RELAY.ARPA,
      RRRS-Authors@MIT-MC.ARPA
Subject: Syntactic extensions to Scheme

I would like to point out that I believe that MIT Scheme has more
power in its syntactic extension mechanism than is necessary or
desirable.  In particular, I have found that there are only two
general scenarios for macro use (please correct or expand on this):

----------------------------------------------------------------------

The first case is the local use of a macro to eliminate syntactic
repetition.  For example, suppose one wanted to say something like:

(define <var1> (lambda (x) (vector-ref x 1)))
(define <var2> (lambda (x) (vector-ref x 2)))
...
(define <varn> (lambda (x) (vector-ref x n)))

in this case a local macro could be used profitably, as in (MIT
Scheme):

(let-syntax ((make-ref
	      (macro (var index)
		`(DEFINE ,var
		   (LAMBDA (X)
		     (VECTOR-REF X ,index))))))
  (make-ref <var1> 1)
  (make-ref <var2> 2)
  ...
  (make-ref <varn> n))

The combination of LET-SYNTAX and MACRO used here gives sufficient
power to do local definitions like this, and also to have defined the
macro somewhere else, say, and access it later by name, as in

(let-syntax ((make-ref the-make-ref-macro)) ...)

Note that this makes no explicit use of the concept of syntax table,
despite the fact that it is implemented using that mechanism.

The issue of what environment in which the binding value of the
LET-SYNTAX form is evaluated is important here, and in fact is
specified externally by passing an explicit environment to the syntax
expander program as described by Jinx earlier.  But in practice, local
macros such as these require only the normal global environment, and
any local procedures can be defined using something like:

(let-syntax ((make-ref
	      (let ()
		(define ...)
		(define ...)
		(macro ...))))
  ...)

A particular difference between this mechanism and the DEFINE-SYNTAX
mechanisms described by JAR and Jinx is that, psychologically, it is
less likely that someone would be confused about what environment and
at what time the binding value of the LET-SYNTAX would be evaluated.
Such confusion is still possible, but I believe it is easier to think
of the binding value as being separate from the rest of the code than
in the case where the macro definition appears as just another top
level definition.

----------------------------------------------------------------------

The second case is the definition of a whole language of syntactic
extensions, which will be used over a large body of code.  An example
of this usage is my recent implementation of the Edwin editor, in
which a number of macros for defining editor commands, variables, and
modes were used throughout much of the source code.  I believe that
this case is the one that normally provides much of the trouble.

I have taken the following conservative approach (I suspect that this
will draw some good criticism; my only response is that it has proven
adequate to date):

* I have assumed that each type of syntactic "language" will
correspond directly to a particular syntax-table.  The
single-inheritance mechanism used by syntax tables is sufficient for
many needs.

* I have assumed that definition of the syntactic extensions is
syntactically separate from their use.  This implies that the syntax
defined by the extensions is NOT available for use at the time that
the definitions of the extensions are processed by the syntactic
expander.  (I hope that this wording is sufficiently general that it
does not restrict my comments to MIT Scheme's implementation.)

In practice, this means the following thing:  that the syntax
definitions reside in a separate file(s) from the source code that
refers to them, and that the definitions do not become effective until
the file(s) is loaded.

Here is an example of how one would define some syntax:

(define edwin-syntax-table
  ;; This means the parent of this syntax table is the "normal" one.
  (make-syntax-table system-global-syntax-table))

(syntax-table-define edwin-syntax-table 'define-command
  (macro ...))

(syntax-table-define edwin-syntax-table 'define-variable
  (macro ...))

etceta.  Supposing the above expressions to be evaluated in some
environment, then the following code could be evaluated (or compiled
without evaluation):

(using-syntax edwin-syntax-table

  (define-command ("↑R Forward Character" argument)
    ...)

  (define-variable "Comment Multi Line"
    ...)

  ...

  )

The major advantage of using this approach is that the scoping
problems associated with macros are sidestepped, since the
environments in which everthing happens are eval-time environments,
rather than syntax-time environments.  Also, the confusion caused by
mixing syntactic and semantic definitions in the code is eliminated.

It can (easily) be argued that this separation is a drawback as well.
I think that this is more a problem of presentation than anything
else.  In particular, given the standard file-oriented methods of
maintaining systems, there is only one ordering or definitions, which
applies for both editing and evaluation.  More sophisticated systems,
which I believe many people are now developing, would allow the
editing presentations to be separate from the evaluation order.

----------------------------------------------------------------------

In summary, I think that the DEFINE-SYNTAX and DEFINE-MACRO mechanisms
in both T and MIT Scheme are not particularly useful, and in fact are
confusing.  Their convenience I believe to be dubious, although I will
understand if there is disagreement on this point.  I do not see that
they add any real power that is not available in the cases I have
outlined above through the other mechanisms I describe.

In passing, I would like to note that I DO NOT believe that scoping of
syntactic keywords should be related to scoping of environment
variables.  I think that the only reason that this has ever been
considered a reasonable idea is because of the (perhaps regrettable)
choice to make the notation used for syntactic forms and combinations
identical.  However, I would be curious to see if KMP's semantics
sheds new light on this issue.

The other issue, about the use of SCode, is not so clear.  In general,
I have tried to assume that syntactic extensions map from one domain
to another.  Assuming that the two domains are separate is a
generality that turns out to have advantages in implementation, as it
allows the use of SCode, while not precluding purely source-to-source
macroexpansion, nor T's method of "absolute special forms".  One of
the examples that Jinx presented violated this principle (see the use
of WHILE-XFORM in the second example).  I am not really sure how to
handle this problem, but the separation of the domain and range of the
syntax mapping seems like a good principle to start with.

∂15-Nov-85  1251	JAR@MIT-MC.ARPA 	testing, testing, ...  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Nov 85  12:50:52 PST
Date: Fri, 15 Nov 85 15:57:41 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  testing, testing, ...
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].719559.851115.JAR>

Several people have wondered whether they are still on the list.  This
message is intended to confirm that y'all still are.  The two most
recent messages were:

    Date: 12 Nov 1985 1035-CST
    From: Don Oxley <OXLEY%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
    Subject: PC Scheme Implementation Information

    Date: Fri, 1 Nov 85 14:47:58 EST
    From: Paul Hudak <Hudak@YALE.ARPA>
    Subject: Re: will the real current continuation please stand up

Don Oxley's message may have been lost (although I've never before known
MC's mailer to lose a message); I'll re-send it if I get deluged with
reports of non-receipt.

∂17-Nov-85  1547	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford.ARPA 	Stream command processing (long message)  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 17 Nov 85  15:47:38 PST
Received: from mitre-bedford.ARPA by MIT-MC.ARPA 17 Nov 85 18:42:26 EST
Full-Name: 
Organization: The MITRE Corp., Bedford, MA
Received: by linus.RESEARCH (4.12/4.7)
	id AA26603; Fri, 15 Nov 85 15:06:32 est
Date: Fri, 15 Nov 85 15:06:32 est
From: John D. Ramsdell <linus!ramsdell@mitre-bedford.ARPA>
Posted-Date: Fri, 15 Nov 85 15:06:32 est
Message-Id: <8511152006.AA26603@linus.RESEARCH>
To: scheme@mit-mc.ARPA
Subject: Stream command processing (long message)



While I am an avid fan of Scheme, I find myself frustrated by how
difficult it is to program some stream processing tasks in Scheme
compared with the difficulty of programming the same tasks in UNIX.
Your typical UNIX hacker can whip together some concoction of awk, grep,
sed, yacc, etc. to solve these kinds of problems very quickly.  But it
is quite a pain in Scheme.  Even more painful is the fact that it is
very hard to use someone else's stream processing programs.

I would like to propose having two standard top level environments for
Scheme.  One is the one we all know and love, and the other would be the
stream command processor (SCP).  This top level environment would map a
stream like syntax into a simple composition of Scheme functions.  The
map would follow a simple convention, so that inexperienced users could
easily modify or creat new functions to be used in the composition.

I have no suggestion as to the particular syntax to be used; I will use
a UNIX like syntax with no implied endorsement.  I will give an example
of a simple map from this syntax to compositions of Scheme functions
using continuation streams (CSTREAMS).  The continuation is not the same
one you get when you use call-with-current-continuation.  Cstreams are
defined by:

; Continuation streams are procedures of one argument
; which is the procedure's continuation.
; A continuation is a procedure of two arguments,
; a stream element, and a the next stream.

; cstream = (lambda (continuation)
;               Compute element and next-cstream.
;               (continuation element next-cstream))

A port is turned into a cstream with:

(define (read-cstream port)
 (lambda (c)
  (c (read port) (read-cstream port))))

and a cstream is turned into something that works as an argument to
call-with-output-port using:

(define (print-cstream cstream)
 (lambda (port)
  (letrec
   ((continuation
     (lambda (element cstream)
      (if (ecse? element)
          'print-done
          (begin
           (print element port)
           (cstream continuation))))))
   (cstream continuation))))

Cstream manipulation functions have the signature:

(lambda (input-cstream . arguments) ...)  ==> output-cstream.

For example, the cstream mapping function looks like:

; => a cstream that results from mapping elements of cstream
; with a procedure of one argument.
(define (map-cstream cstream procedure)
 (letrec
  ((next-cstream
    (lambda (cstream)
     (lambda (c)
      (cstream
       (lambda (element cstream)
        (if (ecse? element)
            (ecs c)
            (c (procedure element) (next-cstream cstream)))))))))
  (next-cstream cstream)))


The SCP would translate a command that looks like

map-cstream list <lists.scm >more-parens.scm

into the expression

(call-with-output-file
    "more-parens.scm"
    (map-cstream
        (call-with-input-file
            "lists.scm"
            read-cstream)
        list))

For a more complex example, SCP would translate the following:

filter-cstream symbol? <lists.scm | map-cstream list >single-level-list.scm

into

(call-with-output-file
    "single-level-list.scm"
    (filter-cstream
        (map-cstream
            (call-with-input-file
                "lists.scm"
                read-cstream)
            list)
        symbol?))

The set of stream functions are easily extended by writting functions that
expect a cstream for their first argument and return a cstream.

I am not particularly attached to my representation of streams, and the
streams in Sussman and Abelson's book would also do the trick.  I am
most interested in an commonly aggreed upon stream processing system
that encourages the interchange of stream functions, just as the Revised
Revised Report on Scheme encourages interchange of Scheme functions.
Then Scheme hackers will definitely be kings of stream processing.

John

Here is some code to play with:
-----------
;;; -*- Mode: LISP -*-

; Continuation Streams.

; Continuation streams are procedures of one argument
; which is the procedure's continuation.
; A continuation is a procedure of two arguments,
; a stream element, and a the next stream.

; cstream = (lambda (continuation)
;               Compute element and next-cstream.
;               (continuation element next-cstream))

(define (error-cstream message)
 (lambda (c)
  c                                             ; ignore continuation.
  (error message)))

(define *ecse*					; Used to identify the empty continuation stream.
 '*ecse*)

; Is the cstream element the empty cstream element?
(define (ecse? x)
 (eq? x *ecse*))

(define past-end-of-cstream
 (error-cstream "Read past end of cstream"))

; the empty continuation stream.
(define ecs
 (lambda (c) (c *ecse* past-end-of-cstream)))

(define (ecs? cstream)
 (cstream 
  (lambda (element cstream)
   cstream                                      ; ignore cstream.
   (ecse? element))))

; => cstream which is cstream0 appended to cstream1.
(define (append-cstreams cstream0 cstream1)
 (letrec
  ((next-cstream
    (lambda (cstream)
     (lambda (c)
      (cstream
       (lambda (element cstream)
        (if (ecse? element)
            (cstream1 c)
            (c element (next-cstream cstream)))))))))
  (next-cstream cstream0)))

; => cstream which is a fair merge of cstream0 and cstream1.
(define (interleave-cstreams cstream0 cstream1)
 (lambda (c)
  (cstream0
   (lambda (element cstream)
    (if (ecse? element)
        (cstream1 c)
        (c element (interleave-cstreams cstream1 cstream)))))))

; => a cstream that results from mapping elements of cstream
; with a procedure of one argument.
(define (map-cstream cstream procedure)
 (letrec
  ((next-cstream
    (lambda (cstream)
     (lambda (c)
      (cstream
       (lambda (element cstream)
        (if (ecse? element)
            (ecs c)
            (c (procedure element) (next-cstream cstream)))))))))
  (next-cstream cstream)))

; Returns a cstream containing elements that satisfy the predicate.
(define (filter-cstream cstream predicate)
 (letrec
  ((next-cstream
    (lambda (cstream)
     (lambda (c)
      (cstream
       (lambda (element cstream)
        (if (ecse? element)
            (ecs c)
            (let ((next-cstream (next-cstream cstream)))
             (if (predicate element)
                 (c element next-cstream)
                 (next-cstream c))))))))))
  (next-cstream cstream)))

(define (list->cstream l)			; => cstream with elements in l.
 (if (null? l)
     ecs
     (let ((element (car l))
           (l (cdr l)))
      (lambda (c) (c element (list->cstream l))))))

(define (cstream->list cstream)			; => list of elements in the cstream.
 (let ((l '()))                                 ; The reverse of the result is held here.
  (letrec
   ((continuation
     (lambda (element cstream)
      (if (not (ecse? element))
          (begin
           (set! l (cons element l))
           (cstream continuation))))))
   (cstream continuation))
  (reverse! l)))

(define (read-cstream port)
 (lambda (c)
  (c (read port) (read-cstream port))))

(define (print-cstream cstream)
 (lambda (port)
  (letrec
   ((continuation
     (lambda (element cstream)
      (if (ecse? element)
          'print-done
          (begin
           (print element port)
           (cstream continuation))))))
   (cstream continuation))))

; For more, see J. D. Ramsdell "An Implementation of a Domain Calculus
; Query Language Using Continuation Streams",  M84-56, MITRE Corp.
; Bedford, MA, December 1984.

∂18-Nov-85  1710	@MIT-MC.ARPA:linus!ramsdell@mitre-bedford.ARPA 	read-cstream fix 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Nov 85  17:08:44 PST
Received: from mitre-bedford.ARPA by MIT-MC.ARPA 18 Nov 85 20:35:00 EST
Organization: The MITRE Corp., Bedford, MA
Received: by linus.RESEARCH (4.12/4.7)
	id AA00913; Mon, 18 Nov 85 07:39:48 est
Date: Mon, 18 Nov 85 07:39:48 est
From: John D. Ramsdell <linus!ramsdell@mitre-bedford.ARPA>
Posted-Date: Mon, 18 Nov 85 07:39:48 est
Message-Id: <8511181239.AA00913@linus.RESEARCH>
To: scheme@mit-mc.ARPA
Subject: read-cstream fix

; read-cstream that checks for EOF.
(define (read-cstream port)
 (lambda (c)
  (let ((element (read port)))
   (if (eof-object? element)
       (ecs c)		; close port?
       (c element (read-cstream port))))))


I sent out some undebuged code for read-cstream.
The above version does the correct thing for EOF.

In some applications it may be desirable to delay
the reading of the port.

(define (read-cstream port)
 (let ((element (delay (read port))))
  (lambda (c)
   (if (eof-object? (force element))
       (ecs c)
       (c (force element) (read-cstream port))))))

John

∂18-Nov-85  1744	@MIT-MC.ARPA:JINX@MIT-OZ 	Stream command processing (long message)    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Nov 85  17:43:55 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 18 NOV 85  21:05:03 EST
Date: 18 Nov 1985  21:01 EST (Mon)
Message-ID: <JINX.12160358034.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   "John D. Ramsdell" <linus!ramsdell@MITRE-BEDFORD.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: Stream command processing (long message)
In-reply-to: Msg of 15 Nov 1985  15:06-EST from John D. Ramsdell <linus!ramsdell at mitre-bedford.ARPA>

Why the syntax when
For a more complex example, SCP would translate the following:

filter-cstream symbol? <lists.scm | map-cstream list >single-level-list.scm

into

(call-with-output-file
    "single-level-list.scm"
    (filter-cstream
        (map-cstream
            (call-with-input-file
                "lists.scm"
                read-cstream)
            list)
        symbol?))

∂18-Nov-85  1828	@MIT-MC.ARPA:JINX@MIT-OZ 	Stream command processing (long message)    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Nov 85  18:28:04 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 18 NOV 85  21:32:21 EST
Date: 18 Nov 1985  21:29 EST (Mon)
Message-ID: <JINX.12160363029.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   "John D. Ramsdell" <linus!ramsdell@MITRE-BEDFORD.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: Stream command processing (long message)
In-reply-to: Msg of 15 Nov 1985  15:06-EST from John D. Ramsdell <linus!ramsdell at mitre-bedford.ARPA>

filter-cstream symbol? <lists.scm | map-cstream list >single-level-list.scm

into

(call-with-output-file
    "single-level-list.scm"
    (filter-cstream
	(map-cstream
	    (call-with-input-file
		"lists.scm"
		read-cstream)
	    list)
	symbol?))

----------------------------------------------------------------------
Why the extraneous syntax when you can do the following

(define (>> file-name stream)
  (call-with-output-file file-name stream))

(define (<< file-name)
  (call-with-input-file file-name read-cstream))

(define (|| what . args)
  (lambda (stream)
    (apply what (cons stream args))))

(>> "single-level-list.scm"
    ((|| filter-cstream symbol?)
     ((|| map-cstream list)
      (<< "lists.scm"))))

which except for the parentheses and the fact that it is left-to-right
inverted with respect to Unix is extremely close.

Sorry, but I feel that

(call-with-output-file
    "single-level-list.scm"
    (filter-cstream
	(map-cstream
	    (call-with-input-file
		"lists.scm"
		read-cstream)
	    list)
	symbol?))

is considerably clerarer than Unix-like syntax.  It is also more
powerful since the Unix shell syntax does not allow (as far as I know)
forking or merging streams in interesting ways, both of which scheme
procedures can easily accomodate.

A portable continuation stream top level of the sort you suggest is an
afternoon's worth of work, and does not really add any power or
interesting functionality to the language, so it might as well be
provided as part of the continuation stream utilities.


∂18-Nov-85  1846	@MIT-MC.ARPA:JINX@MIT-OZ 	Incomplete message 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 18 Nov 85  18:46:21 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 18 NOV 85  21:34:42 EST
Date: 18 Nov 1985  21:31 EST (Mon)
Message-ID: <JINX.12160363416.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   scheme@MIT-MC.ARPA
Subject: Incomplete message

Sorry.  I must have spazzed and sent the message too early.

∂19-Nov-85  1327	JAR@MIT-MC.ARPA 	backquote proposal
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 19 Nov 85  13:27:51 PST
Date: Tue, 19 Nov 85 16:30:10 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  backquote proposal
To: RRRS-AUTHORS@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].724256.851119.JAR>

I haven't heard any objection to the backquote proposal.  Unless you
guys reply soon, it will become part of the next edition of the RRRS,
and I'll complain when my programs don't run in your implementations, so
speak up.

Small change: I think the name #!unquote-splice is a little better than
#!splice.  If anyone would like to suggest better names, you're welcome
to.

Reminder: the proposal is that
  `x   is identical to  (#!quasiquote x)
  ,x   is identical to  (#!unquote x)
  ,@x  is identical to  (#!unquote-splice x)
for the purposes of QUOTE and READ.  Also, (#!quasiquote <pattern>) is a
new special form which means the same thing as `<pattern> , and within
a <pattern> one may write (#!unquote <expression>) instead of ,<expression>;
similarly for #!unquote-splice.

(Don't worry, I'll send out a proposed precise description before a new
edition of the RRRS happens.)

I have an implementation of a post-read-time #!quasiquote macro expander
(written in scheme, of course) which I'll send to anyone requesting it.
One interesting feature of it is that it does the "right" thing with
nested backquotes, that is, e.g.
  (equal? '`(a ,b) ``(a ,b))
returns a true value, which isn't the case in most backquote
implementations that I know of.  I don't know whether this behavior is
dictated by my backquote proposal, but it seems like desirable behavior
to me.

Jonathan

∂20-Nov-85  0901	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: backquote proposal 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  09:01:08 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 20 Nov 85 12:02:56 EST
Received: from ti-csl by csnet-relay.csnet id ab12530; 20 Nov 85 11:48 EST
Date: 20 Nov 1985 0943-CST
From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: Re: backquote proposal
To: JAR%mit-mc.arpa@csnet-relay.arpa, 
    RRRS-AUTHORS%mit-mc.arpa@csnet-relay.arpa
cc: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
In-Reply-To: Your message of 19-Nov-85 1712-CST
Received: from csl60 by ti-csl; Wed, 20 Nov 85 10:03 CST

From JAR:

 > I haven't heard any objection to the backquote proposal.  Unless
 > you guys reply soon, it will become part of the next edition of the
 > RRRS, and I'll complain when my programs don't run in your
 > implementations, so speak up.
 > ...
 > (Don't worry, I'll send out a proposed precise description
 > before a new edition of the RRRS happens.)

Is this tongue-in-cheek or are you suggesting/presuming another round
of ``standardization'' for Scheme?

David Bartley
-------


∂20-Nov-85  1214	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  backquote proposal   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  12:14:03 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 20 Nov 85 15:15:56 EST
Received: from indiana by csnet-relay.csnet id ab14216; 20 Nov 85 15:03 EST
Date: Wed, 20 Nov 85 14:05:35 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: JAR@mit-mc.arpa
Subject: Re:  backquote proposal
Cc: RRRS-AUTHORS@mit-mc.arpa

I like the proposed backquote change, especially since it will
allow source pretty-printers to print the original source more
accurately.

However, I do not like the use of "special objects" as special
form keywords, and would prefer to use ordinary identifier names
instead.

The reason is that, at least in my implementation, #! objects are
not symbols, and special form keywords are.  I would very much
like to retain this property, for selfish reasons and because I
think it helps anyone writing program-manipulating programs to
know that special forms always begin with a symbol.

Also, it would not make sense that backquote special forms are
written with the #! if the quote special form is not.

Therefore, I propose that we use the special forms quasiquote,
unquote, and unquote-splice, dropping the #!.

Kent


∂20-Nov-85  1326	JAR@MIT-MC.ARPA 	backquote proposal
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  13:24:03 PST
Date: Wed, 20 Nov 85 16:26:09 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  backquote proposal
To: dyb%indiana.csnet@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of Wed 20 Nov 85 14:05:35 est from Kent Dybvig <dyb%indiana.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].725715.851120.JAR>

    Date: Wed, 20 Nov 85 14:05:35 est
    From: Kent Dybvig <dyb%indiana.csnet at CSNET-RELAY.ARPA>

    I like the proposed backquote change, especially since it will
    allow source pretty-printers to print the original source more
    accurately.

    However, I do not like the use of "special objects" as special
    form keywords, and would prefer to use ordinary identifier names
    instead.

    The reason is that, at least in my implementation, #! objects are
    not symbols, and special form keywords are.  I would very much
    like to retain this property, for selfish reasons and because I
    think it helps anyone writing program-manipulating programs to
    know that special forms always begin with a symbol.

    Also, it would not make sense that backquote special forms are
    written with the #! if the quote special form is not.

OK, I sympathize with this.  What do other people think?

Note that I never said that #!QUASIQUOTE was NOT a symbol.  Things would
work just fine if it was, although it would have to print the same way
it reads.

    Therefore, I propose that we use the special forms quasiquote,
    unquote, and unquote-splice, dropping the #!.

I never suggested making #!UNQUOTE and #!UNQUOTE-SPLICE be special
forms, so I don't think this argument applies to them, except through
guilt by association (i.e. consistency).

I think that flagging the printed representation of these markers with
#! is good since it helps indicate that something peculiar is going on.
There is always the danger that someone will write something like
	(memq z '(quote unquote quasiquote))
and that someone else will lift that code and put it into backquote
form somewhere, say

	(let ((form `(cond ((memq z '(quote unquote quasiquote)) ,value))))
	  (compute form))

and then get the error message "QUASIQUOTE unbound variable" and wonder
what on earth happened.  This violation of referential transparency is
unavoidable with non-local features like backquote, but the #!'s help
mitigate it since they make the violation more voluble.

∂20-Nov-85  1333	JAR@MIT-MC.ARPA 	Backquote algorithm    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  13:32:51 PST
Date: Wed, 20 Nov 85 16:34:57 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Backquote algorithm
To: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of 20 Nov 1985 0950-CST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].725723.851120.JAR>

    Date: 20 Nov 1985 0950-CST
    From: David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

    I'd appreciate it if you'd send me a copy of your quasiquote expander.

Actually I think it'll be easier if I send it to everyone.  I hope
people who don't care about this don't mind if I clutter their mailboxes
with it.

I won't guarantee that this 100% works, but I've tested it a little.

  - Jonathan


;;; An expansion of `x or (#!quasiquote x) is obtained by calling
;;; the procedure EXPAND-QUASIQUOTE with argument x.

;;; The expansion involves only QUOTE forms and calls to LIST, APPEND,
;;; and CONS*.  CONS* is the only nonstandard procedure, and its
;;; semantics could be given by
;;;   (define (cons* x . rest)
;;;     (if (null? rest) x (cons x (apply cons* rest))))
;;; It should be pretty easy to eliminate the use of CONS*, if that's
;;; desirable.

(define (expand-quasiquote x)

  (define quasiquote-marker '#!quasiquote)
  (define unquote-marker    '#!unquote)
  (define splice-marker     '#!unquote-splice)

  (define (finalize-quasiquote mode arg)
    (cond ((eq? mode 'quote) `',arg)
	  ((eq? mode 'unquote) arg)
	  ((eq? mode 'splice)
	   (error ",@ in illegal context"
		   arg))
	  (else `(,mode ,@arg))))

  ;; The continuation argument c is passed two values, mode and arg.
  ;; These are interpreted as follows:
  ;;    mode    arg          meaning
  ;;    QUOTE   x            'x
  ;;    UNQUOTE x            x
  ;;    LIST    (x1 x2 ...)  (LIST x1 x2 ...)
  ;;    CONS*   (x1 x2 ...)  (CONS* x1 x2 ...)
  ;;    APPEND  (x1 x2 ...)  (APPEND x1 x2 ...)

  (define (descend-quasiquote x level c)
    (cond ((not (pair? x)) (c 'quote x))
	  ((interesting-to-quasiquote? x quasiquote-marker)
	   (descend-quasiquote-pair x (1+ level) c))
	  ((interesting-to-quasiquote? x unquote-marker)
	   (cond ((= level 0)
		  (c 'unquote (cadr x)))
		 (else
		  (descend-quasiquote-pair x (- level 1) c))))
	  ((interesting-to-quasiquote? x splice-marker)
	   (cond ((= level 0)
		  (c 'splice (cadr x)))
		 (else
		  (descend-quasiquote-pair x (- level 1) c))))
	  (else
	   (descend-quasiquote-pair x level c))))

  ;; It would be simple to make this generate only a correct expansion;
  ;; most of the complexity here is in order to generate an
  ;; "optimized" expansion.

  (define (descend-quasiquote-pair x level c)
    (descend-quasiquote (car x) level
      (lambda (car-mode car-arg)
	(descend-quasiquote (cdr x) level
	  (lambda (cdr-mode cdr-arg)
	    (cond ((and (eq? car-mode 'quote) (eq? cdr-mode 'quote))
		   (c 'quote x))
		  ((eq? car-mode 'splice)
		   (cond ((and (eq? cdr-mode 'quote) (null? cdr-arg))
			  (c 'unquote
			     car-arg))
			 ((eq? cdr-mode 'append)
			  (c 'append
			     (cons car-arg cdr-arg)))
			 (else
			  (c 'append
			     (list car-arg
				   (finalize-quasiquote cdr-mode cdr-arg))))))
		  ((and (eq? cdr-mode 'quote) (null? cdr-arg))
		   (c 'list
		      (list (finalize-quasiquote car-mode car-arg))))
		  ((or (eq? cdr-mode 'list) (eq? cdr-mode 'cons*))
		   (c cdr-mode
		      (cons (finalize-quasiquote car-mode car-arg)
			    cdr-arg)))
		  (else
		   (c 'cons*
		      (list (finalize-quasiquote car-mode car-arg)
			    (finalize-quasiquote cdr-mode cdr-arg))))))))))

  (define (interesting-to-quasiquote? x marker)
    (and (pair? x)
	 (eq? (car x) marker)
	 (pair? (cdr x))
	 (null? (cddr x))))

  (descend-quasiquote x 0 finalize-quasiquote))


∂20-Nov-85  1743	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Multiple LAMBDA evaluations 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  17:42:43 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 20 Nov 85 20:44:39 EST
Received: from ti-csl by csnet-relay.csnet id ae16553; 20 Nov 85 20:13 EST
Date: 20 Nov 1985 1825-CST
From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: Multiple LAMBDA evaluations
To: RRRS-Authors@mit-mc.arpa
cc: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
Received: from csl60 by ti-csl; Wed, 20 Nov 85 18:38 CST

I have two questions:

(1) Are issues like the following best raised in the general Scheme
    community (e.g., SCHEME@MIT-MC) or here among the RRRS authors?
    I'm a little confused about the intended difference when it comes to
    language issues.

(2) When a given lambda expression is evaluated more than once, is it
    required/allowed/disallowed that the procedure objects returned be
    EQ? to each other?

    The Common Lisp book addresses this issue on page 88: ``In
    situations where a closure of a lambda-expression over the same
    set of bindings may be produced more than once, the various
    resulting closures may or may not be EQ, at the discretion of the
    implementation.''  This allows certain useful optimizations and
    clarifies the semantics of the language a bit.

    My reading of the RRRS is that this interpretation is implicitly
    supported for Scheme; however, there may be other opinions.  Does
    anyone object to adding similar language to the RRRS to clarify
    our intent?

Regards,
David Bartley
-------


∂20-Nov-85  2352	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	trace   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Nov 85  23:46:53 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 21 Nov 85 02:48:32 EST
Received: from tektronix by csnet-relay.csnet id ac18731; 21 Nov 85 2:38 EST
From: Will Clinger <willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
To: scheme@mit-mc.ARPA
Received: from tekchips by tektronix with smtp ; 20 Nov 85 17:05:17 PST
Date: Wednesday, 20 Nov 85 16:52:06 PST
Subject: trace

A long time ago Jonathan asked what people did to trace self-recursive calls
to FACT when FACT is defined using the (DEFINE (FACT ...) ...) syntax.  It
seems to me there are three obvious implementations of the trace facility,
with three distinct semantics:

1.  Trace the variable.  That is, (TRACE FACT) is a special form that turns
into something like (SET! FACT (MAKE-TRACED FACT)).  This is how most
implementations seem to do it, though in some of them (e.g. MacScheme) TRACE
is a procedure and you have to say (TRACE 'FACT).

The disadvantage is that the self-recursive calls are not traced.

2.  Trace the closure.  That is, TRACE is a procedure and (TRACE FACT)
clobbers some field(s) of the data structure used to represent the procedure
stored in the variable FACT.

This will trace the self-recursive calls.  The disadvantage is that it also
will trace calls to FOO where FOO is any variable that happens to hold the
same closure as is stored in the variable FACT.

3.  Trace the code.  That is, TRACE is a procedure and (TRACE FACT)
clobbers the first instruction(s) of the code portion of the closure.

This will trace the self-recursive calls.  The disadvantage is that it also
will trace calls to any procedure obtained by closing the same lambda
expression.  In fact, the precise semantics of this option is likely to
depend upon small details of an optimizing compiler.

It seems to me that implementations 1 and 2 are the most reasonable.  Perhaps
users should be able to choose between the two.

Thanks to Norman Adams for his criticisms of the three implementations.

Peace, Will Clinger


∂21-Nov-85  0745	@MIT-MC.ARPA:JINX@MIT-OZ 	trace    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  07:45:43 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 21 NOV 85  10:39:58 EST
Date: 21 Nov 1985  10:36 EST (Thu)
Message-ID: <JINX.12161030631.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Will Clinger <willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: trace
In-reply-to: Msg of 20 Nov 1985  19:52-EST from Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>

Some comments about your TRACE implementation classification:

I do not think that the disadvantage you point out for option 2 is
undesirable.  TRACE cleary implies a side effect since the behaviour
of some procedure changes.  The point you make is no worse than the
fact that if A and B have the same (eq?) pair as their value, the
effect of SET-CAR! on one will be observed on the other also.  Note
also that an optimizing compiler may decide to invoke FACT on
self-recursive calls bypassing the closure (by directly branching to
the entry point, for example), so this implementation is not
guaranteed to work on self-recursive calls either.

3 is not unreasonable either.  There are situations in which this is
the desired behaviour.  Consider the case of a procedure that returns
procedures, so there may be many instances of these procedures around.
This is common in message passing situations.  It is occasionally
useful to be able to observe the invocations of all these procedures,
rather than the particular one we have a handle on.  A TRACE option
which modifies the code would accomplish this task under most
circumstances.

In the presence of "hairy" enough compilers all implementations lose.
A compiler may decide, for example, to have 27 entry points to a given
procedure, each used by something else, and the TRACE facility would
have to know a fair amount about the actual code generated to be able
to "trap" all possible paths.  Even worse if it decides to open code
the procedure in some places.  The only possible solution in the worst
case is modifying the source code, recompiling and re-generating the
running environment, but even this may not work if the runtime
behaviour depended on events which cannot be duplicated.

MIT-Scheme has switched back and fourth between implementations 2 and
3.  As far as I know it has never used implementation 1.  I like
implementation 2 better, but there are occasions when 3 is desirable,
and the current implementation is implementation 3.  It is also more
likely (though not without problems) that we can make this work even
in the case of compiled code.

∂21-Nov-85  0903	JAR@MIT-MC.ARPA 	description of MacScheme    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  09:02:52 PST
Date: Thu, 21 Nov 85 12:04:39 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  description of MacScheme
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].726747.851121.JAR>

Date: Wednesday, 20 Nov 85 15:31:49 PST
From: Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>
To:   Scheme-Request at mit-mc.ARPA
Re:   description of MacScheme

Implementation:		MacScheme
Implemented by:		Will Clinger, Liz Heller, and John Ulrich
Supported by:		Semantic Microsystems
Hardware:		Apple Macintosh or Lisa (Mac XL).
			Requires 512K RAM, can use up to 16M.
Operating Systems:	Finder (Macintosh); MacWorks (Lisa).
Price/Availability:	$125.  Available since August 1985.
Implementation:		Compiles to interpreted byte code.
Intended Use:		Education, personal computing, AI applications
Contact:		Semantic Microsystems
			4470 S.W. Hall St., Suite 340
			Beaverton, OR  97005
			(503) 643-4539

MacScheme supports all essential and many optional features of the Revised
Revised Report on Scheme.  It includes a compatibility package for use
with the Abelson and Sussman text, but environments are not supported.

The compiler and byte code architecture were described in Clinger's paper
at the 1984 Lisp conference.  Numbers are implemented as a union of 30-bit
fixnums, bignums, and 32-bit flonums; bignum arithmetic is slow.  The
system includes facilities for breaking, tracing, and debugging; most
run-time errors can be repaired in the debugger.  There is a pretty printer.
An escape to machine code is documented for direct access to the Macintosh
Toolbox.

The system includes a simple editor that understands Scheme syntax and
makes good use of multiple windows and the mouse.  This editor runs as a
foreground process while Scheme runs in the background.

MacScheme's speed is comparable to that of similar interpreters (MIT Scheme
on the HP 9836, TI Scheme) when hardware is taken into account.  Non-tail-
recursive procedure calls are relatively slow in MacScheme but tight tail-
recursive loops are relatively fast.  Interpreted MacScheme seems to run
about half as fast as compiled ExperLisp on the Macintosh.

∂21-Nov-85  0920	JAR@MIT-MC.ARPA 	Multiple LAMBDA evaluations 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  09:20:35 PST
Date: Thu, 21 Nov 85 12:22:56 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  Multiple LAMBDA evaluations
To: Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of 20 Nov 1985 1825-CST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].726762.851121.JAR>

    Date: 20 Nov 1985 1825-CST
    From: David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

    (1) Are issues like the following best raised in the general Scheme
        community (e.g., SCHEME@MIT-MC) or here among the RRRS authors?
        I'm a little confused about the intended difference when it comes to
        language issues.

I figure that sending specific, technical implementation and language
design questions only to RRRS-Authors is appropriate since generally
most of us don't have the time to educate the 150 SCHEME list members
about things which will probably confuse or mislead them, and which they
probably don't care much about anyhow.  Messages to RRRS-Authors are
easier to compose since we can sassume more sophistication on the part
of the recipients.  Also, the smaller group can come to consensus on
complicated questions much faster and much less painfully than the
larger group.  I don't mean this to sound elitist, only pragmatic.

    (2) When a given lambda expression is evaluated more than once, is it
        required/allowed/disallowed that the procedure objects returned
        be EQ? to each other?  ... Does anyone object to adding similar
        language to the RRRS to clarify our intent?

This is a good idea; the wording in the CL manual is pretty good.
We definitely want to permit, but not require, things like
	(LET ((Z ...))
  	  (LET ((F (LAMBDA () (LAMBDA () Z))))
            (EQ? (F) (F))))
and
	(EQ? (LAMBDA (X) X) (LAMBDA (Y) Y))
and even
  	(LET ((F (LAMBDA (X) (LAMBDA () X))))
          (EQ? (F 'A) (F 'A)))
to return true.  The usual rule is that if there's any way to
distinguish two objects, EQ? of them must return false, but if there
ISN'T, EQ? is permitted to return true, and in certain special cases
(like that of symbols) is required to return true.  This applies to
closures just as it does to numbers.

Maybe a 2nd edition of the RRRS is in order, say, for next summer?  I'll
even volunteer to oversee its production, if no one else steps forward,
since the number of changes should be pretty small.

∂21-Nov-85  1306	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	re:  backquote  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  13:04:03 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 21 Nov 85 16:06:05 EST
Received: from indiana by csnet-relay.csnet id ae24742; 21 Nov 85 15:25 EST
Date: Wed, 20 Nov 85 18:32:57 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: rrrs-authors@mit-mc.arpa
Subject: re:  backquote

One potential functionality change, at least to Chez Scheme,
is that backquote errors are found at compilation time rather
than at read time.  This is because it will not be possible
(all right, reasonable) for the reader to catch backquoteless
commas if the (quasiquote ...) syntax is allowable as a
replacement for backquote.

In any case, this strikes me as a feature, not a bug, since
the compiler can generally produce more informatitve error
messages than the reader.

Not only that, but we might find some meaning for (unquote x)
not inside a quasiquote.  How about (eval x)?

Kent


∂21-Nov-85  1324	JAR@MIT-MC.ARPA 	trace   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  13:22:35 PST
Date: Thu, 21 Nov 85 11:44:01 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  trace
To: willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA
cc: SCHEME@MIT-MC.ARPA
In-reply-to: Msg of 20 Nov 85 16:52:06 PST from Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].726726.851121.JAR>

    Date: Wednesday, 20 Nov 85 16:52:06 PST
    From: Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>

    A long time ago Jonathan asked what people did to trace
    self-recursive calls to FACT when FACT is defined using the (DEFINE
    (FACT ...) ...) syntax.  It seems to me there are three obvious
    implementations of the trace facility, with three distinct
    semantics:

    1.  Trace the variable.  That is, (TRACE FACT) is a special form
    that turns into something like (SET! FACT (MAKE-TRACED FACT)).  This
    is how most implementations seem to do it, though in some of them
    (e.g. MacScheme) TRACE is a procedure and you have to say (TRACE
    'FACT).

    The disadvantage is that the self-recursive calls are not traced.

    ...

Thanks for your exposition.  I was too lazy to articulate all this when
I sent out my earlier message, but it's what I had in mind.

For alternative 1., note that the procedure MAKE-TRACED could, in
principle, "look inside" the code for the procedure and produce a new
procedure, with new code, whose self-calls were traced.  This still does
not imply a side-effect on the traced procedure or on its code.

I think all three alternatives have their place, but that (1) is
probably the safest and most useful, and if MAKE-TRACED did as I
suggest, I think it would be adequate.  The others are potentially
dangerous, especially when applied to "system" procedures like
WRITE-CHAR.

[Of course this is implementation-specific; I'm certainly not suggesting
that a standard debugging interface should exist.]

∂21-Nov-85  1324	@MIT-MC.ARPA:CPH@MIT-OZ 	trace
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  13:22:26 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 21 NOV 85  11:07:36 EST
Date: Thu, 21 Nov 1985  10:46 EST
Message-ID: <CPH.12161032526.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Will Clinger <willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
Cc:   scheme@MIT-MC.ARPA
Subject: trace
In-reply-to: Msg of 20 Nov 1985  19:52-EST from Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>

It seems to me that all three of the options are reasonable, and users
should be able to choose any of them.

∂21-Nov-85  1324	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  13:22:07 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 21 NOV 85  10:50:22 EST
Date: 21 Nov 1985  10:45 EST (Thu)
Message-ID: <JINX.12161032360.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   RRRS-Authors@MIT-MC.ARPA
Subject: Multiple LAMBDA evaluations
In-reply-to: Msg of 20 Nov 1985  19:25-EST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

We should certainly not require that both evaluations return EQ?
objects. 

Note: Is it true that the only way that a lambda expression can be
re-evaluated in the same environment is by using
call-with-current-continuation?

∂21-Nov-85  1805	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	EQ? and procedures, numbers, etc 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  18:04:47 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 21 Nov 85 20:52:49 EST
Received: from tektronix by csnet-relay.csnet id ao26285; 21 Nov 85 18:45 EST
From: Will Clinger <willc%tekchips@tektronix.CSNET>
To: RRRS-AUTHORS@mit-mc.ARPA
Received: from tekchips by tektronix with smtp ; 21 Nov 85 14:46:45 PST
Date: Thursday, 21 Nov 85 13:36:39 PST
Subject: EQ? and procedures, numbers, etc

RRRS says that (EQ? x x) is always true, but it would be better if the value
returned by EQ? were undefined when applied to procedure values and numbers.
The current wording of RRRS forces a formal semantics of Scheme to associate
locations with procedure values and numbers.  These locations have no
purpose other than to make the semantics of EQ? work as in RRRS, and they
make the semantics much uglier.

The ugliness of the semantics results in more complex and less effective
optimizing compilers.

I thought that it would be a cleaner semantics if (EQ? x x) always returned
true, but I was wrong.  It is actually a cleaner semantics if the value of
EQ? is unspecified when both its arguments are procedures and when both its
arguments are numbers.  When strings are immutable (as in the essential
subset of Scheme) EQ? should be unspecified when both its arguments are
strings.  Similarly EQ? should be unspecified when both its arguments are
characters (unless we want to insist that either (1) characters are
represented uniquely (e.g. immediates) or (2) EQ? does something
complicated).

Will Clinger


∂21-Nov-85  1926	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: Multiple LAMBDA evaluations  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  19:25:02 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 21 Nov 85 22:26:54 EST
Received: from ti-csl by csnet-relay.csnet id a028471; 21 Nov 85 22:17 EST
Date: 21 Nov 1985 1817-CST
From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: Re: Multiple LAMBDA evaluations
To: JINX%MIT-OZ@mit-mc.arpa, Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa
cc: RRRS-Authors@mit-mc.arpa, Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
In-Reply-To: Your message of 21-Nov-85 1045-CST
Received: from csl60 by ti-csl; Thu, 21 Nov 85 19:14 CST

From JINX:

  > We should certainly not require that both evaluations return EQ?
  > objects.

I'm more concerned about whether I am ALLOWED to return values that
are EQ?, not that I might be REQUIRED to.

  > Note: Is it true that the only way that a lambda expression can be
  > re-evaluated in the same environment is by using
  > call-with-current-continuation?

No.  Consider the following...

(define foo
  (lambda (msg)
    (case msg
      ...
      ((XXX) (lambda (args) do-something))
      ...)))

Here, FOO returns a closure every time it is called with argument XXX.
I expect that most implementations would ``cons up'' a new closure
object every time.  The following code does the same thing, but the
closures returned are always EQ? to each other.

(define foo
  (let ((xxx-handler  (lambda (args) do-something)))
    (lambda (msg)
      (case msg
	...
	((XXX) xxx-handler)
	...))))

My motivation is to allow an optimizing compiler to map code like the
first into code like the second.  This is related to the traditional
compiler optimization which moves invariant computations out of loops.

Here's another example:

(define bar
  (lambda (x)
    (map (lambda (y) (+ y 13))
	 x)))

I would like to transform this into...

(define bar
  (let ((temp (lambda (y)(+ y 13))))
    (lambda (x)
      (map temp x))))

Regards,
David Bartley
-------


∂21-Nov-85  2015	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 21 Nov 85  19:59:31 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 21 NOV 85  23:01:44 EST
Date: 21 Nov 1985  22:58 EST (Thu)
Message-ID: <JINX.12161165719.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   RRRS-Authors@MIT-MC.ARPA
Subject: Multiple LAMBDA evaluations
In-reply-to: Msg of 21 Nov 1985  19:17-EST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

Your counter examples do not disprove my claim.  In all cases no
lambda expression is evaluated twice in the same environment.  The two
environments (as with JAR's example) may be isomorphic (same variables
and same values), but not identical.  In the absence of incremental
definition, or if there is no handle to these environments, the
distinction is moot, but in the presence of these "features" they are
not the same.  I guess that the difference is that I view environments
as objects (probably influneced because of our dialect), and
conceptually a new one is created every time a lambda expression is
applied, even if this lambda expression has no bindings.

I think that the only cases which force re-evaluation in the same environment
(the way I view them) are contorted examples like

(define fact
  (let ((there&then '()))
    (set! there&then
	  (call-with-current-continuation
	   (lambda (here&now) here&now)))
    (let ((y-like (lambda (x) (there&then x))))		;HERE
      (y-like (lambda (f)
		(lambda (n)
		  (if (= n 0)
		      1
		      (* n ((f f) (-1+ n))))))))))

Note that the 2 lambdas marked by HERE (the explicit one, and the
implicit one in the LET expression) are evaluated twice in the
environment created by the outermost LET.

∂22-Nov-85  1054	@MIT-MC.ARPA:BARTLEY%ti-csl.csnet@CSNET-RELAY.ARPA 	Re: Multiple LAMBDA evaluations  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  10:25:51 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 22 Nov 85 13:12:13 EST
Received: from ti-csl by csnet-relay.csnet id ad04001; 22 Nov 85 12:55 EST
Date: 22 Nov 1985 0928-CST
From: David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Subject: Re: Multiple LAMBDA evaluations
To: JINX%MIT-OZ@mit-mc.arpa, Bartley%CSL60%ti-csl.csnet@csnet-relay.arpa
cc: RRRS-Authors@mit-mc.arpa, Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA
In-Reply-To: Your message of 21-Nov-85 1817-CST
Received: from csl60 by ti-csl; Fri, 22 Nov 85 10:34 CST

  > Your counter examples do not disprove my claim.  In all cases no
  > lambda expression is evaluated twice in the same environment.
  > [...]  I guess that the difference is that I view environments as
  > objects (probably influneced because of our dialect), and
  > conceptually a new one is created every time a lambda expression
  > is applied, even if this lambda expression has no bindings.

Sorry, I've tripped up on another assumption that needs to be
discussed!  In my first example (reproduced below), I assumed that the
DO-SOMETHING in the body of the inner lambda was an expression that
did not reference MSG.  Thus, in a pragmatic sense, it didn't have to
be closed over that part of the environment.  This is the analysis
that permits a compiler to transform

	(define foo
	  (lambda (msg)
	    (case msg
	      ...
	      ((XXX) (lambda (args) do-something))
	      ...)))
into
	(define foo
	  (let ((xxx-handler  (lambda (args) do-something)))
	    (lambda (msg)
	      (case msg
		...
		((XXX) xxx-handler)
		...))))

since I'm moving the lambda relative to its environment.

So, I agree with your point, but I'm shifting the question a bit: Is
there a consensus that these kinds of optimizations are permitted?

To my knowledge, the only way to know whether a procedure object has
closed over the entire ``visible'' environment or just the part of it
which it references is to have something like MIT Scheme's
PROCEDURE-ENVIRONMENT.  This function returns the environment over
which a procedure was closed.  Our implementation of Scheme supports
first-class environments in the MIT sense and has this function, but
we consider it a debugging tool only, and do not guarantee that it
returns the entire environment unless the compilation took place in
``debug mode.''

So, I consider the environment closed over to be an abstraction with
different implementations possible.  Thus, if the environments may or
may not be EQ?, the closures may or may not be EQ?.

Regards,
David Bartley
-------


∂22-Nov-85  1135	@MIT-MC.ARPA:KMP@SCRC-STONY-BROOK.ARPA 	EQ? and procedures, numbers, etc   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  11:35:14 PST
Received: from SCRC-STONY-BROOK.ARPA by MIT-MC.ARPA 22 Nov 85 14:02:00 EST
Received: from DUPAGE.SCRC.Symbolics.COM by SCRC-STONY-BROOK.ARPA via CHAOS with CHAOS-MAIL id 360602; Fri 22-Nov-85 13:58:06-EST
Date: Fri, 22 Nov 85 13:59 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: EQ? and procedures, numbers, etc
To: willc%tekchips@tektronix.CSNET
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-Reply-To: The message of 21 Nov 85 16:36-EST from Will Clinger <willc%tekchips@tektronix.CSNET>
Message-ID: <851122135902.0.KMP@DUPAGE.SCRC.Symbolics.COM>

    Date: Thursday, 21 Nov 85 13:36:39 PST
    From: Will Clinger <willc%tekchips@tektronix.CSNET>

    RRRS says that (EQ? x x) is always true, but it would be better if the value
    returned by EQ? were undefined when applied to procedure values and numbers.

I strongly disagree.

    The current wording of RRRS forces a formal semantics of Scheme to associate
    locations with procedure values and numbers.  These locations have no
    purpose other than to make the semantics of EQ? work as in RRRS, and they
    make the semantics much uglier. The ugliness of the semantics results in 
    more complex and less effective optimizing compilers.

I have yet to see a convincing example of this claim. Note, however, that I consider
object identity to be one of the most indispensible things about symbolic processing
and would not be likely to be willing to give up the only function which predicates
such identity regardless of whether such an example could be constructed. However, 
for now perhaps you could just enumerate some of the troublesome cases for me to respond
to more specifically.

    I thought that it would be a cleaner semantics if (EQ? x x) always returned
    true, but I was wrong.  It is actually a cleaner semantics if the value of
    EQ? is unspecified when both its arguments are procedures and when both its
    arguments are numbers.  When strings are immutable (as in the essential
    subset of Scheme) EQ? should be unspecified when both its arguments are
    strings.  Similarly EQ? should be unspecified when both its arguments are
    characters (unless we want to insist that either (1) characters are
    represented uniquely (e.g. immediates) or (2) EQ? does something
    complicated).

I bet it makes things easier to be able to ignore this distinction. I don't know
if programming ease and code size are always the same as cleanliness. They are
clearly related. It's possible that even O(size) is proportional to O(clean), 
but I doubt that size is proportional to clean. Eg, consider:

 (DEFINE SUCCESSOR (X) (+ X 1))

 (DEFINE SUCCESSOR (X)
   (UNLESS (NUMBERP X) (ERROR "Don't know the successor of ~S" X))
   (+ X 1))

Certainly the first program is smaller. It is probably simpler to write.
It is not be simpler to use and may be harder to use. Whether it is cleaner
seems to me to be in a gray area.

I cite as precedent the case of CALL-WITH-CURRENT-CONTINUATION. Everyone seemed to
agree that it was easier to compile/optimize code which doesn't allow returning 
these upward. The argument for pushing it through was not that it made the 
implementation simpler, since in fact it complicated it. It was instead the fact
that it was (a) at least possible to implement and (b) much simpler to some write 
programs when this feature was available. It seems to me that the situation is
similar for EQ? -- I do not want to give up this feature. You (the compiler writer)
have to solve this problem only once. I (the programmer) will have to solve it
repeatedly if you do not solve it once for me.


∂22-Nov-85  1515	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? and procedures, numbers, etc 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  14:43:56 PST
Received: from THINK-AQUINAS.ARPA by MIT-MC.ARPA 22 Nov 85 17:00:06 EST
Received: from THINK-YON.ARPA by THINK-AQUINAS.ARPA via CHAOS with CHAOS-MAIL id 2185; Fri 22-Nov-85 16:59:24-EST
Date: Fri, 22 Nov 85 16:58 EST
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: EQ? and procedures, numbers, etc
To: KMP@SCRC-STONY-BROOK.ARPA, willc%tekchips%tektronix@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MIT-MC.ARPA, gls@THINK-AQUINAS.ARPA
In-Reply-To: <851122135902.0.KMP@DUPAGE.SCRC.Symbolics.COM>
Message-ID: <851122165853.8.GLS@THINK-YON.ARPA>

KMP is right in identifying the question of object identity
as a key issue.  But there are two separate issues here:

(1) Are two evaluations, of the same LAMBDA-expression, that are
distinct in time permitted to produce objects that are not distinct as
determined by "EQ?"?  In simpler terms, may two things that you might
expect to be different turn out to be the same?  (Call this property
"coalescence".)

(2) Once a single object has been produced and named, is the
implementation allowed to duplicate it at will in such a way as to cause
two distinct references to its name to result in values that are
distinct to "EQ?"?  In simpler terms, may one thing turn out to be two
different things?  (Call this property "splitting".)

Now Common Lisp permits splitting for characters and numbers with
respect to "EQ" (but not with respect to "EQL").  It permits coalescing
for numbers, characters, and closures of lambda expressions.

I feel that splitting is a semantically bad thing to have in a LISP-like
language, because I think name-reference should be free of side effects!
It was introduced into Common Lisp only for the sake of certain
implementational efficiencies.  If one removes EQ from the language and
leaves only EQL, then there is no splitting.  I would have preferred for
EQ to have the current semantics of EQL, but it was too ingrained into
everyone's mind (including mine) that EQ means "compare the pointers",
which is an implementation notion rather than a language notion.

On the other hand, I feel that coalescing is a perfectly legitimate
optimization.  If two objects cannot be distinguished, then it should be
legitimate to merge them.  If there are no RPLACA or RPLACD operations
on CONS cells, then hash-consing is a legitimate optimization (and,
indeed, perhaps EQ should be required to behave as EQUAL on CONS cells
in the absence of such side effects!).  It is important to have some
means of generating distinct objects, but it is not clear that
lambda-expressions need to be that means.

It is not always legitimate to coalesce two closures, but frequently a
static analysis can determine that no distinguishing side effects are
possible and that therefore two closures would be operationally
identical.

In short, my feelings are: splitting, no: (EQ? X X) should always be true;
coalescing, maybe: it can be a legitimate optimization.

--Guy


∂22-Nov-85  1628	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	Re: trace    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  16:23:06 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 22 Nov 85 19:24:05 EST
Received: from tektronix by csnet-relay.csnet id ai07029; 22 Nov 85 18:41 EST
From: Norman Adams <adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
To: tektronix!jinx%mit-oz@mit-mc.ARPA
Cc: willc%tektronix.csnet@CSNET-RELAY.ARPA, scheme@mit-mc.ARPA
Fcc: Out
Received: from tekchips by tektronix with smtp ; 22 Nov 85 12:45:49 PST
Date: Friday, 22 Nov 85 12:32:13 PST
Subject: Re: trace
In-reply-to: Your message of 21 Nov 1985  10:36 EST (Thu).,             <JINX.12161030631.BABYL@MIT-OZ>

  TRACE cleary implies a side effect since the behaviour
  of some procedure changes.  

This is not obvious to me.  TRACE reports on an activity in the
system.  The action of the traced procedure is unchanged.  Just to
be extreme,  TRACE might be implemented with external hardware, 
something like a really smart logic analyzer. 

I think we can understand the meaning of the phrases "trace the
variable," "trace the closure," and "trace the code" independent of the
particular implementations.  Is there some concurrence about what an
unsophisticated user expects when he or she writes (TRACE FOO)?  I think
it is undesirable that the effect depends on the form of the DEFINE.  I
also think it is confusing to have indirect recursions appear in the
TRACE output, when the self recursions are ommitted.  

I guess this is a result of (define (v0 v1...) ...)  being subtley
different than (define v0 (lambda (v1 ...) ...))  in the treatment of
v0.  I don't see any advantage to having this difference, aside from
possible runtime efficiency.

   In the presence of "hairy" enough compilers all implementations lose.

Given that we know the desired effect of TRACE in terms of the language,
the implementor of an optimizing compiler can choose to support TRACE or
provide some coherent preemption of it.  In the presence of an
optimizing compiler, I don't see how to make trace independent of the
compiler without preemting either the compiler or the TRACE facility.

-Norman Adams


∂22-Nov-85  2038	@MIT-MC.ARPA:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re: backquote proposal    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  20:38:01 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 22 Nov 85 23:40:19 EST
Received: from indiana by csnet-relay.csnet id a009014; 22 Nov 85 23:28 EST
Date: Fri, 22 Nov 85 15:32:26 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: Bartley%csl60%ti-csl.csnet@CSNET-RELAY.ARPA
Subject: Re: backquote proposal
Cc: rrrs-authors@mit-mc.arpa

Chez Scheme performs the optimization you refer to, in the case
where no free variables are referenced in the lambda expression.
I see nothing wrong with it, since closing is not an explicit
allocation operation in the same sense as cons or make-vector.

Kent


∂22-Nov-85  2101	@MIT-MC.ARPA:JINX@MIT-OZ 	Multiple LAMBDA evaluations  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  21:01:26 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 23 NOV 85  00:03:20 EST
Date: 23 Nov 1985  00:01 EST (Sat)
Message-ID: <JINX.12161439266.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   David Bartley <Bartley%CSL60%ti-csl.csnet@CSNET-RELAY.ARPA>
Cc:   RRRS-Authors@MIT-MC.ARPA
Subject: Multiple LAMBDA evaluations
In-reply-to: Msg of 22 Nov 1985  10:28-EST from David Bartley <Bartley%CSL60%ti-csl.csnet at CSNET-RELAY.ARPA>

I guess the main difference is how the system is viewed.  We view the
system as an interpreted system primarily, and compilation is
something we put up with only for the sake of efficiency on the kinds
of machines we unfortunately have to work with.  Ideally compilation
preserves the behaviour even as far as things like TRACE or
PROCEDURE-ENVIRONMENT are concerned, thus those optimizations would
not be allowed in the absence of declarations.  In practice, given the
limitations of the hardware we deal with, we allow some of these
conceptual declarations to be implicit in the compiler (otherwise
there would be no use to compiling in the first place).  Thus we
tolerate potential incompatibilities between compiled and interpreted
code because of efficiency constraints.  We view compilation as
something that happens only after the code has being debugged
significantly, so the above procedures are unlikely to be used at this
stage.

∂22-Nov-85  2157	@MIT-MC.ARPA:JINX@MIT-OZ 	trace    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 22 Nov 85  21:57:42 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 23 NOV 85  00:59:34 EST
Date: 23 Nov 1985  00:32 EST (Sat)
Message-ID: <JINX.12161444926.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   tekchips!adams%tektronix.csnet@CSNET-RELAY.ARPA
Cc:   scheme@MIT-MC.ARPA, tektronix!jinx%MIT-OZ@MIT-MC.ARPA,
      willc%tektronix.csnet@CSNET-RELAY.ARPA
Subject: trace
In-reply-to: Msg of 22 Nov 1985  15:32-EST from tekchips!adams%tektronix.csnet at CSNET-RELAY.ARPA


      TRACE cleary implies a side effect since the behaviour
      of some procedure changes.  

    This is not obvious to me.  TRACE reports on an activity in the
    system.  The action of the traced procedure is unchanged.  Just to
    be extreme,  TRACE might be implemented with external hardware, 
    something like a really smart logic analyzer. 

The values returned by the traced procedure are the same (hopefully),
but there is certainly a change in behaviour in the procedure.  It
prints (writes?) some stuff which it was not printing before, so its
behaviour has changed, irrelevant of whether you implement the TRACE
facility by modifying the procedure (closure, code, or variable), or
APPLY.

What you say is similar to saying that SET-CAR! does not really change
the appropriate pair, but rather changes the CAR procedure so that if
it sees that its argument is the "modified" pair, it gives the new
"car" as its answer, as opposed to the "real" car.  Sorry, but I think
you are just playing word games.

    .. is undesirable that the effect depends on the form of the DEFINE.  I
    also think it is confusing to have indirect recursions appear in the
    TRACE output, when the self recursions are ommitted.  

What do you mean by indirect recursions?  I think you are too harsh on
DEFINE.  It seems from your message that you would be upset if in the
following

(define (fact n)
  (if (= n 0)
      1
      (* n (fact (-1+ n)))))

self recursive calls were not displayed, but you would be perfectly willing 
to tolerate that behaviour in 

(define fact
  (letrec ((fact (lambda (n)
		   (if (= n 0)
		       1
		       (* n (fact (-1+ n)))))))
	  fact))

.  I see no difference.  As far as I'm concerned, I would like to see
all instances where the object which FOO is bound to (eq? problems
again) is (conceptually) invoked.  This obviously presupposes a
particular model of evaluation, but that is probably true of each
user.

I don't think that we will be able to agree on what the "right"
behaviour is since the "right" behaviour depends on the situation, and
there are probably cases which we have not included in our
classification where any of them will not do exactly what we want.

∂25-Nov-85  1133	@MIT-MC.ARPA:KMP@SCRC-STONY-BROOK.ARPA 	EQ? and procedures, numbers, etc   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Nov 85  11:33:19 PST
Received: from SCRC-STONY-BROOK.ARPA by MIT-MC.ARPA 25 Nov 85 14:31:44 EST
Received: from DUPAGE.SCRC.Symbolics.COM by SCRC-STONY-BROOK.ARPA via CHAOS with CHAOS-MAIL id 362279; Mon 25-Nov-85 14:22:54-EST
Date: Mon, 25 Nov 85 14:24 EST
From: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Subject: EQ? and procedures, numbers, etc
To: gls@THINK-AQUINAS.ARPA
cc: KMP@SCRC-STONY-BROOK.ARPA, willc%tekchips%tektronix@CSNET-RELAY.ARPA,
    RRRS-AUTHORS@MIT-MC.ARPA
In-Reply-To: <851122165853.8.GLS@THINK-YON.ARPA>
Message-ID: <851125142400.0.KMP@DUPAGE.SCRC.Symbolics.COM>

Hmm, let me pose a few concrete examples to test that you and I agree.

You called this splitting:

 [1] (LET ((X C) (Y C))
       (EQ? X Y))

You and I seem to agree that evaluating this expression should always
yield true. Further, I suggest that the following are also in the same 
category and assume that we both agree that these should -always- return 
true as well:

 [1a] (LET ((F (LAMBDA () C)))
        (EQ? (F) (F)))

 [1b] (LET ((F (LAMBDA () '(ANY EXPRESSION))))
        (EQ? (F) (F)))

You called this coalescing:

 [2] (LET ((F (LAMBDA () (LAMBDA () 3))))
       (EQ? (F) (F)))

I agree with you that it is reasonable for either of {true,false} to be
returned from evaluating this. I suggest that the following are special
cases of the same situation, and that it may not be possible to predict
which of {true,false} will be returned:

 [2a] (LET ((X '(ANY EXPRESSION))
	    (Y '(ANY EXPRESSION)))
	(EQ? X Y))

 [2b] (LET ((F (LAMBDA () '(ANY EXPRESSION)))
	    (G (LAMBDA () '(ANY EXPRESSION))))
	(EQ? (F) (G)))

Among other things, 2b is important because of code constructed by
expressions like:
 `(LET ((F (LAMBDA () ',EXP))
	(G (LAMBDA () ',EXP)))
    (EQ? (F) (G)))
We would like to constrain the semantics of the resulting expression to not
be perturbed by first writing the expression to an intermediate file and
then re-reading it.

Put another way -- with the exception of objects like symbols (which are
intentionally interned), sharing of memory should not affect the semantics
of an expression (though it may affect its perceived behavior). On the
other hand, certain identifiable patterns of data flow should be defined
to preserve sharing in a well-defined way, in order to ease certain 
programming tasks and also (for not reasons that are not unrelated) to 
allow various theorems, transformations, proofs, and optimizations to be
conveniently written about those patterns.


∂25-Nov-85  1426	@MIT-MC.ARPA:JINX@MIT-OZ 	EQ? and procedures, numbers, etc  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Nov 85  14:25:57 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 25 NOV 85  17:20:22 EST
Date: 25 Nov 1985  17:17 EST (Mon)
Message-ID: <JINX.12162152284.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>
Cc:   gls@AQUINAS.THINK.COM, RRRS-AUTHORS@MIT-MC.ARPA,
      willc%tekchips%tektronix@CSNET-RELAY.ARPA
Subject: EQ? and procedures, numbers, etc
In-reply-to: Msg of 25 Nov 1985  14:24-EST from Kent M Pitman <KMP at SCRC-STONY-BROOK.ARPA>

I don't know if GLS agrees with you, but I certainly do.

∂25-Nov-85  1551	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	trace, language vs. implementation    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Nov 85  15:48:32 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 25 Nov 85 18:50:13 EST
Received: from tektronix by csnet-relay.csnet id ae04345; 25 Nov 85 18:39 EST
From: Norman Adams <adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
To: tektronix!jinx%mit-oz@mit-mc.ARPA
Cc: scheme@mit-mc.ARPA
Fcc: Out
Received: from tekchips by tektronix with smtp ; 25 Nov 85 11:15:24 PST
Date: Monday, 25 Nov 85 11:06:35 PST
Subject: trace, language vs. implementation
In-reply-to: Your message of 23 Nov 1985  00:32 EST (Sat).,             <JINX.12161444926.BABYL@MIT-OZ>

>>> TRACE cleary implies a side effect since the behaviour
>>> of some procedure changes.  
>>
>> This is not obvious to me.  TRACE reports on an activity in the
>> system.  The action of the traced procedure is unchanged.  Just to
>> be extreme,  TRACE might be implemented with external hardware, 
>> something like a really smart logic analyzer. 
>
> The values returned by the traced procedure are the same (hopefully),
> but there is certainly a change in behaviour in the procedure.  It
> prints (writes?) some stuff which it was not printing before, so its
> behaviour has changed, irrelevant of whether you implement the TRACE
> facility by modifying the procedure (closure, code, or variable), or
> APPLY.

There is no requirement that the procedure print the message.  My
analogy to a logic analyzer still holds.  Something external to the
procedure could be report on the activity of the procedure. 

You seem to be unwilling to consider the behavior of TRACE separate
from its implementation.  

> What you say is similar to saying that SET-CAR! does not really change
> the appropriate pair, but rather changes the CAR procedure so that if
> it sees that its argument is the "modified" pair, it gives the new
> "car" as its answer, as opposed to the "real" car.  Sorry, but I think
> you are just playing word games.

I find this comparison unconvincing.  First, SET-CAR!  is a construct of
the language; TRACE is a command to the programming environment.  My
guess would be that you do not make this distinction; though, I think it
would be a mistake not to.  Second, SET-CAR! is defined to have a side
effect, TRACE can be specified without resorting to side effects:
"After issuing (TRACE <proc>) the procedure trace facility with report
calls to and returns from <proc>."  I note that you wrote "TRACE", not
"TRACE!".  I think there is more to what I am saying than word games.  

Your example demonstrates that the semantics of "side-effect" can be
implemented without apparent side effect; the reverse is also possible
(you can implement FP in C).

-Norman 








∂25-Nov-85  1802	@MIT-MC.ARPA:adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	Re: trace    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Nov 85  17:27:21 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 25 Nov 85 18:50:25 EST
Received: from tektronix by csnet-relay.csnet id ag04345; 25 Nov 85 18:40 EST
From: Norman Adams <adams%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
To: tektronix!jinx%mit-oz@mit-mc.ARPA
Cc: scheme@mit-mc.ARPA
Fcc: Out
Received: from tekchips by tektronix with smtp ; 25 Nov 85 12:25:15 PST
Date: Monday, 25 Nov 85 12:09:52 PST
Subject: Re: trace
In-reply-to: Your message of 23 Nov 1985  00:32 EST (Sat).,             <JINX.12161444926.BABYL@MIT-OZ>


> >  .. is undesirable that the effect depends on the form of the DEFINE.  I
> >   also think it is confusing to have indirect recursions appear in the
> >  TRACE output, when the self recursions are ommitted.  
> 
> What do you mean by indirect recursions?  I think you are too harsh on
> DEFINE.  It seems from your message that you would be upset if in the
> following
> 
> (define (fact n)
>   (if (= n 0)
>       1
>       (* n (fact (-1+ n)))))
> 
> self recursive calls were not displayed, but you would be perfectly willing 
> to tolerate that behaviour in 
> 
> (define fact
>   (letrec ((fact (lambda (n)
> 		   (if (= n 0)
> 		       1
> 		       (* n (fact (-1+ n)))))))
> 	  fact))
> 
> .  I see no difference.

There may be no good answer. My point was that if I write

 (define (foo x)
    ... (foo x) ...
    ... (bar x) ...  )

 (define (bar x)
    ... (foo x) ...
    ... (bar x) ... )

that I am going to see calls from FOO to BAR, and from BAR to FOO,
but not from FOO to FOO, or from BAR to BAR.  I find this property of 
this variant of DEFINE strange.  At least is this version:

> (define fact
>   (letrec ((fact (lambda (n)
> 		   (if (= n 0)
> 		       1
> 		       (* n (fact (-1+ n)))))))
> 	  fact))
> 

there are two different variables named FACT apparent in the code the
user wrote.

>   As far as I'm concerned, I would like to see
> all instances where the object which FOO is bound to (eq? problems
> again) is (conceptually) invoked.  This obviously presupposes a
> particular model of evaluation, but that is probably true of each
> user.

Great!  Here are some possible trace facilities (specified in terms
of the language):

(1) Trace all calls to the procedure which is the value of a given
    variable (what you said).  "trace the closure"

(2) Trace all evaluations of a particular combination (specify 
    a call in a particular piece of source).  "trace the source"

(3) Trace all evaluations of all combinations where the procedure in the
    combination was obtained by evaluating a given variable.
    "trace the variable"

(4) Trace all evaluations of all combinations where the procedure is
    a value that resulted from the evaluation of a given lambda-expression.
    (You choose how to specify the lambda). "trace the code"

Given that we decided that some or all of these were useful, we might
discuss the relative difficulty of implementing them; or perhaps, 
how these might or might not be supported in the presence of an
optimizing compiler.  This was the point of my first message.

I do not think that TRACE merrits  all this discussion.  I do think
there is an important issue at hand: how to implement a language that
is both efficient and easy to debug.   Perhaps a change in the focus
of this discussion would show up some interesting differences in 
Scheme implementation philosophies.

-Norman


∂25-Nov-85  1812	@MIT-MC.ARPA:JINX@MIT-OZ 	trace, language vs. implementation
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 25 Nov 85  18:00:54 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 25 NOV 85  20:57:36 EST
Date: 25 Nov 1985  20:42 EST (Mon)
Message-ID: <JINX.12162189507.BABYL@MIT-OZ>
From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>
To:   tekchips!adams%tektronix.csnet@CSNET-RELAY.ARPA
Cc:   scheme@MIT-MC.ARPA, tektronix!jinx%MIT-OZ@MIT-MC.ARPA
Subject: trace, language vs. implementation
In-reply-to: Msg of 25 Nov 1985  14:06-EST from tekchips!adams%tektronix.csnet at CSNET-RELAY.ARPA

When I said

>>>> TRACE cleary implies a side effect since the behaviour
>>>> of some procedure changes.  

I did not mean to imply that the side effect was done on the procedure
(variable, etc.)  but that a side effect was done somewhere.  In
particular, APPLY can be changed to take care of TRACE.

>There is no requirement that the procedure print the message.  My
>analogy to a logic analyzer still holds.  Something external to the
>procedure could be report on the activity of the procedure. 

You've moved the side effect one level out.  Conceptually SOMETHING,
SOMEWHERE, is taking some action which it would not have taken before.
I do not know what you call this if it is not a side effect.

1>You seem to be unwilling to consider the behavior of TRACE separate
1>from its implementation.  

>> What you say is similar to saying that SET-CAR! does not really change
>> the appropriate pair, but rather changes the CAR procedure so that if
>> it sees that its argument is the "modified" pair, it gives the new
>> "car" as its answer, as opposed to the "real" car.  Sorry, but I think
>> you are just playing word games.

2>I find this comparison unconvincing.  First, SET-CAR!  is a construct of
2>the language; TRACE is a command to the programming environment.  My
2>guess would be that you do not make this distinction; though, I think it
2>would be a mistake not to.  Second, SET-CAR! is defined to have a side
2>effect, TRACE can be specified without resorting to side effects:
2>"After issuing (TRACE <proc>) the procedure trace facility with report
2>calls to and returns from <proc>."  I note that you wrote "TRACE", not
2>"TRACE!".  I think there is more to what I am saying than word games.  

Please be consistent.  Either TRACE is a part of the language (vs. "the
programming environment") or it isn't.  If it is part of the
programming environment we should not worry about semantics since no
portable code will (hopefully) depend on its behaviour.  Its
implementation is the only interesting part.  If it is part of the
language my analogy holds and we lose anyway since it involves a
side effect (which was my original point).

I agree with JAR in that we should not attempt to agree on debugging
tools, since debugging is a highly personal activity, and we would be
asking people to support models which do not necessarily agree with
their own.  In other words, TRACE is part of the programming system
and we should not constrain it in any way in the same way that we do
not ask people to use a particular editor.  There is too much personal
taste involved.

∂26-Nov-85  0049	@MIT-MC.ARPA:willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA 	EQ? and procedures etc 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Nov 85  00:48:51 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 26 Nov 85 03:51:04 EST
Received: from tektronix by csnet-relay.csnet id aa07476; 26 Nov 85 3:38 EST
From: Will Clinger <willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
To: RRRS-AUTHORS@mit-mc.ARPA
Received: from tekchips by tektronix with smtp ; 25 Nov 85 16:35:13 PST
Date: Monday, 25 Nov 85 16:29:22 PST
Subject: EQ? and procedures etc

Ok, it's pretty clear that people want (EQ? X X) to be true.  I bow to the
majority, but I want to discuss some of the points that have been raised.
This is a long message.

----------------------------------------------------------------

Will:
  The current wording of RRRS forces a formal semantics of Scheme to associate
  locations with procedure values and numbers.  These locations have no
  purpose other than to make the semantics of EQ? work as in RRRS, and they
  make the semantics much uglier. The ugliness of the semantics results in
  more complex and less effective optimizing compilers.

Kent:
 I have yet to see a convincing example of this claim....  However, for now
 perhaps you could just enumerate some of the troublesome cases for me to
 respond to more specifically.

Will:
I made about four claims in the paragraph Kent cites, all of which are
debatable, and I'm not sure which one(s) he doesn't believe so I will run
through all of them.  First of all, neither the Muchnik-Pleban semantics nor
the semantics I wrote for my 1984 Lisp conference paper can handle the
semantics of EQ? as in RRRS.  The problem is that the domain equation for
expressed values is something like

	E = {#!true, #!false, #!null} +
		F +				; procedure values
		R +				; numbers
		Q +				; symbols
		LxL +				; pairs
		L* +				; vectors
		L*				; strings

where L is the domain of locations and + is a disjoint union.  The equation
for procedure values is F = E* --> K --> C, so the EQ? procedure sees a
procedure as a higher order (mathematical) function, not as a pointer to a
data structure encoding the higher order function.  The obvious fix is to
change the equation for procedure values to be F = L x (E* --> K --> C).
This fix is necessary in order that an implementation be *allowed* to say
for example that (EQ? (lambda (x) x) (lambda (y) y)) is false.

If EQ? does indeed say that the two identity procedures are different, then
we have an interesting example of Guy's "splitting" (which he claims to
dislike): both arguments are the identity procedure, and in all respects
they behave exactly the same except that EQ? says they're different.  Now,
however, if I naively go through the semantics and make the changes implied
by the new domain equation for F, I find that implementations are *required*
to say that (EQ? (lambda (x) x) (lambda (y) y)) is false -- so splitting is
forced upon us.  That naive semantics can be fixed, provided that we agree
on a precise formulation of the circumstances in which an implementation can
say that two procedures are EQ?.  My suggestion that EQ? be left unspecified
on procedure values was prompted by a disagreement over precisely what those
circumstances should be.  Since people don't like that, I now propose that
it's ok to say that two procedure values are EQ? iff the second components
(i.e., elements of E* --> K --> C) are equal.  This is of course undecidable
in general but implementations should be allowed to take advantage of
whatever simple cases they can recognize.  (I expect the MIT philosophy will
disagree.)

Similarly R must have a structure akin to R = L x (mathematical numbers),
but this isn't as troublesome because we seem to agree that it's ok for EQ?
to return true on numbers whenever the difference of the two numbers is
zero, and that EQ? must return false whenever the difference is nonzero.

I think the location-ridden semantics is uglier, but that's a matter of
taste.  I admit that the location-ridden semantics doesn't affect compilers
provided my new suggestion is adopted (that EQ? can use the second component
of procedure values), because most of us were doing precisely the same thing
with the old semantics.  If on the other hand optimizations such as those
raised by David Bartley are disallowed, then compilers are going to be less
effective.  Furthermore the ambitious compilers will be more complex,
because they will still attempt those optimizations whenever the compiler
can prove that the procedures never get passed to the EQ? procedure.  (To
the objection that the compiler could never prove such a thing because the
break key provides access to internals at arbitrary times, I reply that the
compiler has the freedom to define critical sections during which such
interrupts are deferred.)

----------------------------------------------------------------

Kent:
 ...I cite as precedent the case of CALL-WITH-CURRENT-CONTINUATION. Everyone
 seemed to agree that it was easier to compile/optimize code which doesn't
 allow returning these upward. The argument for pushing it through was not
 that it made the implementation simpler, since in fact it complicated it. It
 was instead the fact that it was (a) at least possible to implement and (b)
 much simpler to some write programs when this feature was available. It
 seems to me that the situation is similar for EQ? -- I do not want to give
 up this feature. You (the compiler writer) have to solve this problem only
 once. I (the programmer) will have to solve it repeatedly if you do not
 solve it once for me.

Will:
First class escape procedures greatly simplified the semantics.  Their
semantics is so beautiful you don't even have to see them.  Downward-only
escape procedures have a really ugly semantics.  The same holds for first
class procedures as opposed to downward-only procedures.  Semantic
simplicity often does not correlate with implementational simplicity.  My
complaint about the current definition of EQ? is not that it is hard to
implement -- it isn't -- but that I think its semantics are ugly.  I haven't
always thought that -- I too once thought that (EQ? X X) should always be
true.

(I stand by my comment about semantic ugliness turning into compiler
complexity in this particular case, but in truth I said that for the sake of
people who think of me as a semantic purist who doesn't care about
implementations.  If people now think of me as a hacker who doesn't care
about semantics, well, that's great, my disguise must be working.)

----------------------------------------------------------------

Guy:
 ....may two things that you might expect to be different turn out to be the
 same?  (Call this property "coalescence".) ....may one thing turn out to be
 two different things?  (Call this property "splitting".)

Will:
The problem is that we don't have a precise and independent definition of
what we mean by "expect to be different" and "one thing" until we have a
semantics for EQ?, so we can't use these notions to define EQ?.  (Likewise,
when the RRRS says of certain objects that they "are identical to themselves
and are different from everything else...", it says nothing at all.)  My
earlier reference to (EQ? (LAMBDA (X) X) (LAMBDA (Y) Y)) --> #!FALSE as a
splitting was intended in part to demonstrate that Guy's informal
distinction is probably based on some preconceived semantics for EQ?.  That
would be ok if we could formalize that preconceived semantics and then
sanction particular classes of deviations from it, which is in effect what I
propose above.

----------------------------------------------------------------

Guy:
 I feel that splitting is a semantically bad thing to have in a LISP-like
 language, because I think name-reference should be free of side effects!

Will:
(EQ? + +) --> #!FALSE implies no more of a side effect than (EQ? 1000000
1000000) --> #!FALSE or (<? 3 3) --> #!FALSE or (+ 3 3) --> 6.  All we're
talking about is the value returned by a procedure.  Since procedures can't
be side effected, we can't look to the primitive mutators for guidance, and
we must fall back on the rule that indistinguishable objects should be EQ?.

----------------------------------------------------------------

Guy:
 If two objects cannot be distinguished, then it should be legitimate to
 merge them.  If there are no RPLACA or RPLACD operations on CONS cells, then
 hash-consing is a legitimate optimization (and, indeed, perhaps EQ should be
 required to behave as EQUAL on CONS cells in the absence of such side
 effects!)...

Will:
Hence (EQ? (LAMBDA (X) X) (LAMBDA (Y) Y)) --> #!TRUE should be ok, but we
can't require it (as we could for hashed pairs) because the problem is
undecidable.  The challenge lies in writing a semantics that will allow it
but not require it.  I have stated my belief that the cleanest such
semantics leaves EQ? unspecified on procedures, numbers, etc, but I am
willing to adopt what I believe is an uglier semantics if that's what people
want.

----------------------------------------------------------------

Gerry:
 I think it is essential that (EQ? x x) be true of procedure values.  We
 should be able to think of compound data structures as LAMBDA calculus
 entities (as at the end of section 3.3.1 of Abelson and Sussman -- "Mutation
 is just assignment" -- p 207), and surely we want (EQ? x x) to be true of
 CONSs (else assignment to components such as SET-CAR! will make no sense).

Will:
The lambda calculus has no side effects and no primitive or definable (in
the language) equality predicate that satisfies the rule that equal objects
are behaviorally indistinguishable.  My feeling is that if the lambda
calculus can get along without EQ?, then Scheme should be able to get along
without it also except for those objects that can be stored into.
Nonetheless I think Gerry has expressed the best argument for making EQ? do
something reliable on procedures.

Let me observe, however, that the value of (LET ((FOO FOO)) (LAMBDA ARGS
(APPLY FOO ARGS))) is behaviorally identical to the value stored in FOO when
that value is a procedure object, but there is no similar way to take a pair
and get from it a behaviorally identical but non-EQ? pair without redefining
all the primitive operations on pairs.  Thus if EQ? is supposed to express
something like total behavioral equivalence, then it does a much better job
with pairs than with procedures.  Hence the argument for making EQ? work on
procedures is weaker than the corresponding argument for pairs.

In case anyone is worried, my proposal that EQ? can say that two procedure
values are identical whenever their E* --> K --> C parts are identical
is sufficient to ensure that

	(EQ? (LET ((N 0)) (LAMBDA () (SET! N (1+ N)) N))
	     (LET ((N 0)) (LAMBDA () (SET! N (1+ N)) N)))

is false (ignoring the fact that a compiler could determine that neither
procedure is going anywhere).  It would not guarantee that

	(LET ((N 0))
	  (EQ? (LAMBDA () (SET! N (1+ N)) N)
	       (LAMBDA () (SET! N (1+ N)) N)))

is false (with the same caveat).  In other words, my new proposal seems to
me to do the right thing with respect to object-oriented programming.


∂26-Nov-85  0953	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? and procedures etc 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Nov 85  09:41:30 PST
Received: from THINK-AQUINAS.ARPA by MIT-MC.ARPA 26 Nov 85 11:58:33 EST
Received: from FAUSTINUS.THINK.COM by THINK-AQUINAS.ARPA via CHAOS with CHAOS-MAIL id 2959; Tue 26-Nov-85 11:58:57-EST
Date: Tue, 26 Nov 85 11:57 EST
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: EQ? and procedures etc
To: willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA,
    RRRS-AUTHORS@MIT-MC.ARPA
cc: gls@THINK-AQUINAS.ARPA
In-Reply-To: The message of 25 Nov 85 19:29-EST from Will Clinger <willc%tekchips%tektronix.csnet@CSNET-RELAY.ARPA>
Message-ID: <851126115745.2.GLS@FAUSTINUS.THINK.COM>

Will has raised some very good points.  I need to be more precise about
what I mean.

    Will:
						   ... Guy's informal
    distinction is probably based on some preconceived semantics for EQ?.  That
    would be ok if we could formalize that preconceived semantics and then
    sanction particular classes of deviations from it, which is in effect what I
    propose above.
    ...
    (EQ? + +) --> #!FALSE implies no more of a side effect than (EQ? 1000000
    1000000) --> #!FALSE or (<? 3 3) --> #!FALSE or (+ 3 3) --> 6.  All we're
    talking about is the value returned by a procedure.  Since procedures can't
    be side effected, we can't look to the primitive mutators for guidance, and
    we must fall back on the rule that indistinguishable objects should be EQ?.

Indeed, I have a preconceived semantics for EQ?, namely the semantics
attributed to "=" in logic: the identity function.  A logic may have "="
in it or not, but it has to be included specially.

I view EQ? as a primitive notion: it is the very definition of what it
means for two things to be the same.  I want other parts of the language
to satisfy certain relationships with respect to EQ?.

I define the notion of side effect in terms of EQ?.  If I take two
formally identical computations (that is, expressions that are identical
in every way), and use them as the two arguments to EQ?, then if EQ?
returns #!FALSE I say that a side effect has occurred.  (If EQ? returns
true then that result says nothing one way or the other about whether a
side effect has occurred.)

One of the properties I want in my language is that name-reference be
free of side effects.  That is, if "x" is any name, I expect evaluation
of the form (EQ? x x) to produce #!TRUE.

Note that I have not yet insisted that (EQ? f f) return #!TRUE for any
kind of form f other than a name.  In particular, I have not insisted
that
	(EQ? (LAMBDA (X) X) (LAMBDA (X) X))
return #!TRUE.  This is very different from saying that
	(LET ((Z (LAMBDA (X) X))) (EQ? Z Z))
must return #!TRUE, and indeed I do insist on this latter case.

Note too that I do not insist that beta-conversion be a valid
transformation (and this is why we must be careful to distinguish
	(EQ? (LAMBDA (X) X) (LAMBDA (X) X))
and
	(LET ((Z (LAMBDA (X) X))) (EQ? Z Z)),
for example: we have not yet established substitutability of expressions
for names that represent their values).  Rather, one of the requirements
for beta-conversion is that the resulting program fragment be externally
indistinguishable from the original with respect to side effects (as defined
above).

However, I do have a rule for LET: if x and y are two names (possibly
the same), then (LET ((x y)) (EQ? x y)) returns #!TRUE.  (That is,
LET-binding does not "split".  There is an analogous rule for binding of
LAMBDA-parameters.  This rule can be generalized for arbitrary
side-effect-free expressions y.)

Once again, I insist that referring to a name be free of side effects.
It is also convenient to insist that referring to a constant (numbers
and quoted objects, for example) be free of side effect, but for now we
sidestep the question of whether the expression (+ 6 6) contains the
"same" constant 6 twice or two different constants representing the
mathematical value 6.  I insist that the operation of function calling
per se be free of side effect; if evaluation of a function-call form has
a side effect, then necessarily either the body of the invoked function
has a side effect or one of the argument forms has a side effect.  (This
is why I want references to constant to be side-effect-free: so that I
can claim that if (+ 6 6) has a side effect, it must be in the body of +
because it doesn't come from the references to the name + or to the
constant(s) 6.)

Now, what things in the language shall be permitted to have side
effects?  We could consistently allow a call to + to result in a side
effect, with the result that (EQ? (+ 6 6) (+ 6 6)) might return #!FALSE.
(Since I so far allow the 6's to be distinct, perhaps it is more to the
point to say that (LET ((X 6)) (EQ? (+ X X) (+ X X))) might return
#!FALSE.)  We could interpret this in familiar implementational terms by
saying that + allocates a new location associated with the result, but
the results do have the same mathematical values, and EQUAL? will
compare these values without regard to the location.

But because numerical equality is decidable we might as well say that
(EQ? m n) iff (EQUAL? m n) for numbers m and n and let it go at that.
Such a definition will maintain the desired properties of naming with
respect to EQ?.

On the other hand, because equality of functions is not decidable in
general, we cannot take such an easy way out.  We insist that for two
functions f and g, (EQ? f g) must return #!FALSE if f and g are
operationally distinguishable (that is, if they have differences of
behavior that are detectable within the language).  On the other hand,
it must be the case that (LET ((X f)) (EQ? x x)) returns #!TRUE for any
f, even a function.  Consider the dilemma of poor EQ?: confronted with
two mathematical functions (for which operational equality is
undecidable in general), it could take the safe way out for the first
condition by returning #!FALSE if it can't decide, or it could take the
safe way out for the second condition by returning #!TRUE if it can't
decide; but it cannot do both.  One solution, as Will has pointed out,
is to package a "hint" with every function object, in the form of a
"location".  One should perhaps think of this not as indicating a
location in *memory*, in which the closure is somehow stored, but rather
as an indication of the *(dynamic) location in the code* whose
evaluation produced the function object.  Two compare two closures,
then, one first compares the locations; if they match, then they
resulted from the same evaluation, and so EQ? must return #!TRUE to
satisfy the naming properties.  Otherwise, EQ? looks at that
mathematical functions themselves; and it may return #!TRUE if it can
prove the functions are operationally indistinguishable, but it is
always safe to return #!FALSE in this case.

To summarize: I take EQ? as primitive; I define the notion of side
effect in terms of EQ?; I require the language to obey certain
properties defined in terms of EQ? (and this is why EQ? is special:
because structural properties of the language, such as naming, are
specified in terms of it); and I show that, because of the
undecidability of equality of functions, the use of pure mathematical
functions to represent closures results in a semantically inadequate
model because two requirements on the language cannot be satisfied
simultaneously by the implementation without additional information
(such as a location).  So the use of locations is not a wart, but
critical to the semantics.  Locations are not necessary for mathematical
objects whose equality is decidable, such as numbers.

					    Thus if EQ? is supposed to express
    something like total behavioral equivalence, then it does a much better job
    with pairs than with procedures.  Hence the argument for making EQ? work on
    procedures is weaker than the corresponding argument for pairs.

I propose that two things might happen to be behaviorally equivalent
without being EQ?.  It is precisely because of the undecidability
problem that EQ? cannot determine equivalence; I say only that EQ?
returning #!TRUE implies behavioral equivalence.  (This is why splitting
is bad: I might determine (EQ? X Y) => #!TRUE and later find that X and
Y behave differently, possibly only with respect to EQ? itsefl!)

    In case anyone is worried, my proposal that EQ? can say that two procedure
    values are identical whenever their E* --> K --> C parts are identical
    is sufficient to ensure that

	    (EQ? (LET ((N 0)) (LAMBDA () (SET! N (1+ N)) N))
		 (LET ((N 0)) (LAMBDA () (SET! N (1+ N)) N)))

    is false (ignoring the fact that a compiler could determine that neither
    procedure is going anywhere).  It would not guarantee that

	    (LET ((N 0))
	      (EQ? (LAMBDA () (SET! N (1+ N)) N)
		   (LAMBDA () (SET! N (1+ N)) N)))

    is false (with the same caveat).  In other words, my new proposal seems to
    me to do the right thing with respect to object-oriented programming.


I think this is exactly right.

--Guy


∂26-Nov-85  1201	JAR@MIT-MC.ARPA 	EQV? and procedures etc
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 26 Nov 85  12:00:53 PST
Date: Tue, 26 Nov 85 15:03:10 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  EQV? and procedures etc
To: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of 25 Nov 85 16:29:22 PST from Will Clinger <willc%tekchips%tektronix.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MIT-MC.ARPA].733803.851126.JAR>

While we're stirring up the EQ? muck, I would like to stir up some EQV?
muck.

I would like it if the description of EQV? did NOT appeal to the
definition of EQ?.  In fact, I would like it to be deterministic.  That
is, while the meaning of (EQ? x y) is a function of an implementation,
the meaning of (CAR x) is not, and I would like EQV? to have the same
deterministic status as CAR.

A consequence of this is that unlike EQ?, the domain of EQV? would be
incomplete, that is, it might be an error to call it on certain
combinations of arguments.  For example, if both arguments are
procedures, or both arguments are inexact numbers, it should be
undefined (and implementations are permitted to signal an error).

Examples:  (EQV? 'A CAR)   =>  false   - different types
	   (EQV? (CONS 1 2) (CONS 1 2))   =>  false
	   (LET ((Z (FOO))) (EQV? Z Z))   =>  true
	       this would hold for any expression (FOO)
	   (EQV? (LAMBDA (X) X) (LAMBDA (Y) Y))
	        =>  wrong   - returning a consistent answer in all
		    implementations would impose horrible
		    constraints on implementations
	   (EQV? CAR CDR)  =>  wrong   - similarly
	   (EQV? #i1 #i1)  =>  wrong   - similarly

Of course, the exact behavior of EQV? in undefined situations is
unspecified; implementations may find it more efficient to fail to
detect domain errors than to detect them.

In other words, I want EQV? to strive to be the true mathematical
equality-of-denotation predicate which we would like to have but can't
(both for implementation and decidability reasons).  It would
necessarily then have an incomplete domain.

If people seriously object to this I won't bother trying to make it more
precise; if they don't, and someone wants it to be made more precise,
I'll try to do so.

∂27-Nov-85  2057	@MIT-MC.ARPA:wagle%indiana.csnet@CSNET-RELAY.ARPA 	EQ? on pointers to functions 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 27 Nov 85  20:57:29 PST
Received: from CSNET-RELAY.ARPA by MIT-MC.ARPA 27 Nov 85 23:47:07 EST
Received: from indiana by csnet-relay.csnet id a015950; 27 Nov 85 23:29 EST
Date: Wed, 27 Nov 85 17:30:50 est
From: Perry Wagle <wagle%indiana.csnet@CSNET-RELAY.ARPA>
To: scheme%indiana.csnet@CSNET-RELAY.ARPA
Subject: EQ? on pointers to functions

re:  the great EEEK! (I mean EQ?) debate, or

  Is "(EQ? (call/cc (lambda (k) (k k))) (call/cc (lambda (k) k)))" true?

-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  The generic LISP semantics I carry around in my head says that if an
expression terminates, it returns a pointer.  The things pointers point to
have types (like "function", "integer", "string", etc).

  Therefore my functionality equations are meta Will Clinger's equations.
That is, where he has "integer", I have "pointer to integer".  As what I
deal with are pointers, my semantics are very simple if I ignore type.  I
can well imagine that Will's semantics wants to barf when it tries to
incorporate the wierdness of EQ? on its level.

  EQ? is very natural in my semantical domain.  I resist "flattening" as
then we get Pascal, where we can't talk about eval, interpreters, and all
those powerful meta tools that made LISP better.  Yeah, Pascal is simpler
and more tractable to our puny proof methods, but watching SCHEME backslide
to Pascal is horrifying to watch from here on the outside (I do CogSci).

-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  The problem is not that you shouldn't have the type "pointer to function",
but that the collapsing of the same or different texts at different times to
an identical pointer is very complex and potentially unpredictable to a user
(unlike symbol or number collapsing).  I don't see that this is cause to
spaz and declare EQ? undefined on pointers to functions, or to remove EQ?
altogether (?!?), as I can still write useful and correct programs that EQ?s
on pointers to functions.  (I use ASSQ a lot).

-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  Proposal:  Expressions that evaluate to a pointers to functions return
UNIQUE pointers.  How this is done is up to the implementation.  My
abstraction is that a function consists of a unique head, and a potentially
shared body.  The head might be a cons cell with some sort of unique
timestamp in the CAR and a pointer to the body in the CDR, or the head might
be a box pointing to the body; these two methods would allow EQUAL? to work
on functions.  Another way is the have the head be a "jump body" machine
instruction, but this would kill EQUAL?, though one could keep a pointer to
body in the type info of the function...

-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  Another proposal would be to be to have a way to tell the compiler that
"HEY!, this is a UNIQUE function, dammit!  Don't you dare try to point
something else here!".  This might be part of a more general facility to
prevent sharing of environment tails, etc.

-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  I am trying more to be provocative here than "here's the solution!"ish.


∂04-Dec-85  1518	@MIT-MC.ARPA:msr@rice.ARPA 	Query: Scheme on a Sun?    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 4 Dec 85  15:18:10 PST
Received: from rice.ARPA by MIT-MC.ARPA  4 Dec 85 18:08:15 EST
Received: by rice.ARPA (AA28225); Wed, 4 Dec 85 17:01:38 CST
Date:     Wed,  4 Dec 85 16:56:44 CST
From: Mark Riggle <msr@rice.ARPA>
Subject:  Query: Scheme on a Sun?
To: scheme@mit-mc.ARPA
Message-Id: <168.msr.Dione@Rice>

Does anyone know of any good implementations of Scheme that runs on a
68000 Unix based workstation, specifically a Sun workstation?
Replies to msr@rice.arpa. 
Many thanks.



∂12-Dec-85  1515	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	[Postmaster@SCRC-STONY-BROOK.ARPA: Unable to deliver letter]   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 12 Dec 85  15:14:46 PST
Received: from GODOT.THINK.COM by MIT-MC.ARPA 12 Dec 85 17:24:40 EST
Received: from desiderius by GODOT.THINK.COM via CHAOS; Thu, 12 Dec 85 16:45:07 est
Date: Thu, 12 Dec 85 16:45 EST
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: [Postmaster@SCRC-STONY-BROOK.ARPA: Unable to deliver letter]
To: KMP@SCRC-STONY-BROOK.ARPA
Cc: rrrs-authors@MIT-MC.ARPA, gls@THINK-AQUINAS.ARPA
In-Reply-To: <851209230127.8.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>
Message-Id: <851212164505.4.GLS@THINK-DESIDERIUS.ARPA>

    [GLS -- This went to RRRS-AUTHORS and was explicitly CC'd to you but didn't
     succeed in sending directly to you so I'm retrying; you may have
     seen it already on RRRS-AUTHORS, but in case that failed, too, I'm
     risking redundancy. -kmp]

    Hmm, let me pose a few concrete examples to test that you and I agree.

    You called this splitting:

     [1] (LET ((X C) (Y C))
	   (EQ? X Y))

    You and I seem to agree that evaluating this expression should always
    yield true. Further, I suggest that the following are also in the same 
    category and assume that we both agree that these should -always- return 
    true as well:

     [1a] (LET ((F (LAMBDA () C)))
	    (EQ? (F) (F)))

     [1b] (LET ((F (LAMBDA () '(ANY EXPRESSION))))
	    (EQ? (F) (F)))

    You called this coalescing:

     [2] (LET ((F (LAMBDA () (LAMBDA () 3))))
	   (EQ? (F) (F)))

    I agree with you that it is reasonable for either of {true,false} to be
    returned from evaluating this. I suggest that the following are special
    cases of the same situation, and that it may not be possible to predict
    which of {true,false} will be returned:

     [2a] (LET ((X '(ANY EXPRESSION))
		(Y '(ANY EXPRESSION)))
	    (EQ? X Y))

     [2b] (LET ((F (LAMBDA () '(ANY EXPRESSION)))
		(G (LAMBDA () '(ANY EXPRESSION))))
	    (EQ? (F) (G)))

    Among other things, 2b is important because of code constructed by
    expressions like:
     `(LET ((F (LAMBDA () ',EXP))
	    (G (LAMBDA () ',EXP)))
	(EQ? (F) (G)))
    We would like to constrain the semantics of the resulting expression to not
    be perturbed by first writing the expression to an intermediate file and
    then re-reading it.

    Put another way -- with the exception of objects like symbols (which are
    intentionally interned), sharing of memory should not affect the semantics
    of an expression (though it may affect its perceived behavior). On the
    other hand, certain identifiable patterns of data flow should be defined
    to preserve sharing in a well-defined way, in order to ease certain 
    programming tasks and also (for not reasons that are not unrelated) to 
    allow various theorems, transformations, proofs, and optimizations to be
    conveniently written about those patterns.


I agree with you in all these details.
--Guy

∂13-Dec-85  1355	@MIT-MC.ARPA:gls@THINK-AQUINAS.ARPA 	EQ? again, already
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Dec 85  13:55:05 PST
Received: from GODOT.THINK.COM by MIT-MC.ARPA 13 Dec 85 16:34:33 EST
Received: from jehosephat by GODOT.THINK.COM via CHAOS; Fri, 13 Dec 85 16:31:46 est
Date: Fri, 13 Dec 85 16:31 EST
From: Guy Steele <gls@THINK-AQUINAS.ARPA>
Subject: EQ? again, already
To: rrrs-authors@MIT-MC.ARPA
Cc: gls@THINK-AQUINAS.ARPA
Message-Id: <851213163145.5.GLS@THINK-JEHOSEPHAT.ARPA>

From a message I received by papermail (for obscure reasons) from Will
Clinger, I infer that I may have confused a lot of people out there.
When I said that I take EQ? as my axiomatic notion of identity, I
neglected to say that I reject the further definition of EQ? in such
implementational terms as comparison of pointers.  I expect EQ? to
behave more like EQV? (or like the Common Lisp EQL), so it might have
been more clear if I had used EQV? everywhere instead of EQ? in my last
long message.  To put it another way, I constrain the meaning of my
identity operation by positing not only such requirements as that (EQ? X
X) always be true for X any name, but also that (EQ? (+ X Y) (+ X Y)),
(EQ? (* X Y) (* X Y)), and so on, so that numbers of the same type and
value are always EQ? (or EQV?, if you insist).  I argued for changing
Common Lisp EQ to have the semantics EQL now has, but there was too much
implementation tradition behind EQ and so EQ remained unchanged.  I feel
it is a mild pity that RRRS has made this same mistake.
--Guy

∂13-Dec-85  1850	JAR@MIT-MC.ARPA 	EQ? again, already
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Dec 85  18:50:44 PST
Date: Fri, 13 Dec 85 21:53:08 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  EQ? again, already
To: gls@AQUINAS.THINK.COM
cc: RRRS-AUTHORS@MIT-MC.ARPA
In-reply-to: Msg of Fri 13 Dec 85 16:31 EST from Guy Steele <gls at THINK-AQUINAS.ARPA>
Message-ID: <[MIT-MC.ARPA].753457.851213.JAR>

    Date: Fri, 13 Dec 85 16:31 EST
    From: Guy Steele <gls at THINK-AQUINAS.ARPA>

    I feel it is a mild pity that RRRS has made this same mistake.

If EQ? were banished to the realm of "implementation-dependent" and
satisfying few portable axioms (e.g. it could look at the machine state
when given two EQV? numbers), and EQV? were considered the portable
equality primitive, what would you have it do with procedures?

More importantly, I would like to see evaluation of LAMBDA-expressions
not be a side-effect, but not only is a contradictory assumption wired
into Abelson & Sussman's book (according to Sussman), the problem is
undecidable if by equality you mean what compilers would like equality
to mean, that is extensional equality ("f computes the same return value
and machine state as g given the same input arguments and machine
state").  Which would you prefer:
  (a) to define EQV? to "be an error" when both arguments are procedures
      (this implies that implementations would be encouraged to signal
      errors, of course),
  (b) to define LAMBDA to be a side-effect,
  (c) to rule out optimizations which would inhibit "intensional"
      comparison of procedures, or
  (d) make EQV? to be implementation-dependent (and thus put it in the
      same flea-bitten bag as EQ?)?  I think those are the only alternatives.

Actually, now that I think of it, option (c), intensional procedure
comparison, could be made to work, conceivably.  E.g. EQV? on two
procedures could use EQV? to compare bignums representing some canonical
form of the source (or object?) code (alpha- and maybe beta-converted to
some sort of normal form, and maybe other things) and the presumably
cons-cell-like cells which hold values of variables.  Then indeed

(EQV? (LAMBDA (X) (LIST X Z)) (LAMBDA (Y) (LIST Y Z)))

would be defined to return true, and we could intern object code, do
CSE, and so on.  I haven't though about this possibility, but I suspect
it would be very complicated to implement, and would inhibit some
important optimizations.

I echo my previous simple request (to which no one has replied - I guess
that everyone agrees): permit implementations of EQV? to signal an error
when given arguments that are both procedures.

∂13-Dec-85  1854	JAR@MIT-MC.ARPA 	EQ? again, already
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 13 Dec 85  18:54:08 PST
Date: Fri, 13 Dec 85 21:56:36 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  EQ? again, already
To: gls@AQUINAS.THINK.COM
cc: RRRS-AUTHORS@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].753459.851213.JAR>

Typo in previous message (result of electronic editing): flush the two
words "More importantly, ".

∂14-Dec-85  0603	@MIT-MC.ARPA:HAL@MIT-OZ 	intro computer science course at Brandeis    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 14 Dec 85  06:03:45 PST
Received: from MIT-OZ by MIT-MC.ARPA via Chaosnet; 14 DEC 85  08:25:33 EST
Date: Sat, 14 Dec 1985  08:22 EST
Message-ID: <HAL.12167035500.BABYL@MIT-OZ>
From: HAL%MIT-OZ@MIT-MC.ARPA
To:   scheme@MIT-MC.ARPA
Subject: intro computer science course at Brandeis


This past semester, Brandeis University changed its introductory
computer science subject to use "Structure and Interpretation of
Computer Programs" and Scheme (running on Texas Instruments PCs).

The following essay is by Harry Mairson, who was in charge of the
subject.


\magnification = 1200
\centerline
{\bf Structure and Interpretation of Computer Programs}
\centerline{Autumn Semester, 1985}
\medskip
\centerline{\sl by Harry Mairson}
\bigskip
\bigskip
\parskip = 5pt plus1pt minus .5pt

This year, the Brandeis computer science department introduced a new
introductory course for its prospective majors.  {\sl Structure and
Interpretation of Computer Programs}, a textbook and novel curriculum
under development at MIT for several years, replaced a standard course
teaching Pascal and modular programming.  I taught the course in
cooperation with Harold Abelson, one of the MIT professors who
developed the curriculum.  As the course comes to a conclusion this
term, I would like to make a few comments about its contents, and why
I believe it has been and will continue to be a success at Brandeis.

First of all, ``Structure and Interpretation of Computer Programs'' is
a sophisticated and high-powered course, presenting to students with
no presumed background in computer science an intensive introduction
to the subject of computation.  Among the subjects presented in this
course are: induction and recursion, lambda calculus, actor models,
tail recursion, orders of growth, abstraction mechanisms, data-driven
and procedure-driven (i.e., ``message passing'') computation, data
structures, substitution and environment models of computation, stream
processing, applicative- and normal-order evaluation, how interpreters
and compilers work, and logic programming.  All this as an {\sl
introduction} to computer science! I did not learn about many of these
subjects until I was in graduate school, and some I learned only while
teaching this innovative course.

Such an ambitious curriculum cannot succeed without a substantial
commitment of resources from both students and the University.  Students
worked 15 to 20 hours a week on this course, sometimes more.  The
computer science department bought 18 Texas Instruments Professional
Computers, with the latest version of the Scheme programming language that
was practically hot off the press; there were fewer than three students per
personal computer.  Hal Abelson gave a two-hour master class each week.
I gave two one-hour recitation lectures, plus interminable tutorials.
(I had no fixed office hours, tried to be in as much as possible, and
students badgered me with questions constantly, sometimes until early
morning...)  Three teaching assistants, Brandeis graduate students
Larry Bookman, Xiru Zhang, and Brandeis senior Moises Lejter ran
one-hour tutorials every week in groups of four to five students,
and worked as tutors in the laboratory.  They were unflagging in their
dedication and patience.  In addition, they were joined by three MIT
undergraduates, David Alcocer, Jos\'e Capo, and Scott Heeschen, providing
on-the-spot counseling and tutoring in the midst of programming crises.
The MIT students were great, but as I joked to them on their arrival,
``I'm delighted to have you help, and I can't wait to throw you out.''
Next year, Brandeis undergraduates will take their places.

The kids in the class knew every resource we could conceivably provide
them was there.  Given that total commitment, they showed beyond any
doubt their own commitment and willingness to work real hard and absorb
the material.

This course has something new and profound to say about computation and
learning.  With no time wasted, it immediately plunges into a discusssion
of the {\sl semantics} of computation, and treats almost peripherally
the questions of syntax.  The importance of this approach can best be
explained by considering the difference between learning a foreign
language (say, French) and a computer language.

Before learning my first word of French, I already understood the semantics
of the language, since ``meaning'' means the same thing in English as it
does in French, despite any Gallic claims to the contrary: the French
talk about tables, chairs, families, taxes, good food, vacations; they use
the same verbs, adjectives, and adverbs as we do, and essentially the same
notions of time.  So ``learning French'' meant learning a new grammar to
express the same ideas and thoughts I already knew how to express
in English.

The same cannot be said for learning a computer language, because there the
overriding questions of the {\sl d\'ebutant} are: what is the computer
doing, what {\sl can} it do, and what does my program {\sl mean?}
The grammar of any programming language is far simpler than that of
French; given enough compulsiveness, anyone can learn to make sure that all
the semicolons are in the right place, that for every {\tt BEGIN} there
is an {\tt END}, that left and right parentheses match.  These grammatical
rules are annoying, but not conceptually deep.

It happens that this course is taught using the Scheme language, a dialect
of a more famous programming language called Lisp.  But as the authors of 
the text write, ``After a short time we forget about syntactic details
of the language (because there are none), and get on with the real issues.''
The Scheme language is used because it expresses easily a wide range of
computational processes, but these processes, and not the language itself,
are the centerpiece of this course.

Such an emphasis, as well as many other aspects of the course, is in
the best tradition of liberal education.  The course is not simply a
compendium of ``current'' tricks of the programming trade that will 
doubtless change in the next six months, but presents a foundation from
which today's and tomorrow's issues and controversies in computer science
can be understood and put into perspective.  I expect this course will 
teach students to think for themselves.

Computer science often attracts the ire of specialists in other academic
fields, principally physicists and mathematicians, but philosophers and
just about everyone else too, because it seems so narrow and self-referential
that it doesn't relate to other fields of study.  This course goes a long
way to healing the wounds of that misconception, as well as teaching
students a healthy appreciation for the respective fields that are
not simply the ancestors of computer science, but its much needed partners
in the pursuit of knowledge and understanding.  That means I want my
students to take lots of math, physics, and philosophy courses, and know
what these subjects are about!

For example, no discussion of the meaning of language can take place outside
the tradition of philosophy and its profound contribution to the understanding
of language.  In the Scheme language, for example, the meaning of a simple
expression like {\tt (cons x y)} can be explored on many levels, none of them
artificial.  The mechanism used by the computer to evaluate this expression
can be implemented in several ways that are substantially different:
{\tt (cons x y)} could be interpreted as a memory structure, an integer,
or a procedural abstraction.  On the other hand, the expression has
precise meaning simply in its fixed use with respect to the other
constructs of the Scheme language.

I spent one lecture describing these two radically different points of
view, showing how the former view of ``meaning as implementation'' is the
direct descendant of logical atomism in the tradition of Bertrand Russell
and his followers, while the latter idea of ``meaning as use'' is a
natural consequence of the philosophy of language as proposed in the 
later writings of Ludwig Wittgenstein.  Similarly, in a discussion of the
so-called ``environment model'' of computation, the subject of denotation
is explored: we understand how classical problems of referential
transparency in language are resolved, and how conceptions of meaning and
time relate to each other.  The semantics of computation becomes a
controlled laboratory where we can discover more about the complex
relationship of meaning and language.

Apart from the usual arithmetic programming examples, the course draws on
problems and examples from mathematics and physics.  In one two-week problem
set, for example, the students implemented a video game called ``Lunar
Lander,'' where a spaceship with a fixed amount of fuel must be landed
under a gravitational force without crashing.  In doing so, they experimented
with a variety of landing strategies.  The principal goal of the problem set
is to teach the students how to use something called lambda expressions,
a programming language construct borrowed from mathematical logic.  But the
problem set also makes the students think about models of physical reality,
where computation is not simply {\sl sui generis} but an analog of the
physical world.  They implemented an optimal fuel-efficient landing
strategy, and I made them understand the ideas of calculus and elementary
physics that justifies calling the strategy optimal.

In other material developed in the course, methods of data structuring are
used to implement symbolic differentiation as in the differential calculus.
Stream processing provides a method for understanding integration, and
shows how the arithmetic of infinite power series can be automated.  The
connections of these methods to the Macsyma system of ``symbolic
mathematics,'' a computer system of great use to researchers in science
and mathematics, are no mere coincidences.

Finally and most profoundly, the material presented in this course teaches
a wonder and respect for computation.  It is true, as often repeated in that
hackneyed phrase, that computers only do what we tell them to.  Stated
otherwise, a computational process evolves in a deterministic fashion from
an initial state, subject to fixed and mechanical constraints on the nature
of that evolution.  But the potential richness, depth, and variety of that
evolution, as this course teaches, is truly mind-boggling.  In the 
introduction to their book, Harold Abelson and his co-author Gerald Jay
Sussman, also of MIT, write the following:

\bigskip

\item{}
We are about to study the idea of a {\sl computational process.}
Computational processes are abstract beings that inhabit computers.  As
they evolve, processes manipulate other abstract things called {\sl data.}
The evolution of a process is directed by a pattern of rules called a
{\sl program.}  People create programs to direct processes.  In effect,
we conjure the spirits of the computer with our spells.

\item{}
A computational process is indeed much like a sorcerer's idea of a spirit.
It cannot be seen or touched.  It is not composed of matter at all.  
However, it is very real.  It can perform intellectual work.  It can
answer questions.  It can affect the world by disbursing money at a bank
or by controlling a robot arm in a factory.  The programs we use to conjure
processes are like a sorcerer's spells.  They are carefully composed from
symbolic expressions in arcane and esoteric {\sl programming languages}
that prescribe the tasks that we want our processes to perform.

\item{}
A computational process, in a correctly working computer, executes programs
precisely and accurately.  Thus, like the sorcerer's apprentice, the
novice programmer must learn to understand and to anticipate the
consequences of his conjuring.

\bigskip

In the same way that a biochemist marvels at DNA as a code that directs
the amazing growth and development of living organisms, I marvel as I watch
computer programs provide the code for the creation and interaction of
Abelson and Sussman's computational ``spirits.'' Just as
a chemist sees the elementary chemical building blocks 
of nature interact, combine,
and recombine as she pours solutions together, the computer scientist
sees the rich and seemingly unpredictible interaction of computational
processes as a result of her procedural incantations.

For all those who have looked askance at the existence of computer science
in the university, Abelson and Sussman have written, ``Underlying our
approach to this subject is our conviction that `computer science' is
not a science and its significance has little to do with computers.
The computer revolution is a revolution in the way we think and in the way
we express what we think.''

I believe that nothing could be more exciting or more important at a
university than to understand the way we think and how we express those
thoughts.  This new introductory course comes face-to-face with these profound
issues, and brings its students into the heart of the consequent
intellectual debate, sometimes pushing them to within striking distance
of the frontiers of research.  I believe it will provide them with tools
to strike out on frontiers of their own, frontiers of personal discovery,
creativity, understanding and synthesizing of knowledge, driven on by
the powerful metaphors that the study of computational processes provide,
and by the personal intellectual success that this course provides them.

This new course demands a great commitment from its students and
teaching staff.  Students have five official ``contact hours'' per
week with the teaching staff, and many more on an informal basis.
Because of that great contact, I believe that this course has another
thing to say that is also profound, though perhaps peripheral to the
issues of computation.  The University is a place for teaching and
learning, not simply for the transmission of information.  Teaching
and learning reinforce the respect, encouragement, and love that any
society or university needs to flourish.  I hope this class says
loudly and clearly that students have a place in the crucial function
of this University, not as passive receivers of knowledge that spouts
from the end of a pedagogical assembly line, but as partners in an
important dialogue that defines what the University is.

I want the students in this class to have learned two things.  First,
how much there is that they don't know.  And second, that they can
learn anything they want.  I hope that they will never forget the
former, and always be inspired by the latter.  Every conceivable thing
was done in this course to provide a fertile and inspiring environment
for learning and discovery.  What could students possibly do under
such circumstances but mature, grow, and learn?

The lesson for the teaching staff in this course is not so different.
While Newton said he saw further because he stood on the shoulders of
giants, I have always preferred Nietzsche's remark that a teacher is
poorly repaid if one only remains a student.  

What a tremendous debt we teachers owe to those who nurtured us!  We
honor those who taught us by nurturing students, and the way we
express that nurturing is to teach students to grow and think for
themselves, so they don't need us any longer.  A friend of mine who is
a physician once said that the responsibility of a doctor is to love
your patients.  I believe above all that the responsibility of a
teacher is to love your students, to show them what is known, and to
inspire them to confront the unknown.  The territory is vast, and
because computer science is still so new, largely unexplored.  The
rewards are great for those who simply press forward.

\bye

∂15-Dec-85  1641	JAR@MIT-MC.ARPA 	[CPH%MIT-OZ: HP 300s]  
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Dec 85  16:40:56 PST
Date: Sun, 15 Dec 85 19:42:55 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  [CPH%MIT-OZ: HP 300s]
To: SCHEME@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].755222.851215.JAR>

I'm forwarding this because I though it might be of general interest.
- Jonathan

Date: Thu, 12 Dec 1985  18:45 EST
From: CPH%MIT-OZ at MIT-MC.ARPA
To:   KGK%Brown.CSNet at CSNET-RELAY.ARPA
Re:   HP 300s

    Have you people put Scheme on these putative ai machines yet? 

    As a matter of fact, would you know of any good source of information
    for these machines? We just got a few and I may be the one to have to
    figure out what they're good for. Like whether it's a research machine
    or an educational machine, things like that.

We have yet to receive the remaining pieces of our model 320s, so I
suppose that the answer to your first question is no.  However, within
several months we will undoubtedly have transferred all of our
implementation to them.

As for your other questions: we have alot of experience with the 200
series machines, which are reputed to be about half the speed of the
300 series.  They seem to have adequate memory for some fairly big
programs, and with the compiler we are now using they run many
benchmarks within a factor of 3 or 4 of a 3600.  So I would say that
they are very adequate for a number of research purposes, and much
more than adequate for educational purposes.

∂15-Dec-85  1919	JAR@MIT-MC.ARPA 	backquote    
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 15 Dec 85  19:19:43 PST
Date: Sun, 15 Dec 85 22:22:11 EST
From: Jonathan A Rees <JAR@MIT-MC.ARPA>
Subject:  backquote
To: ALAN@MIT-MC.ARPA, RRRS-AUTHORS@MIT-MC.ARPA
Message-ID: <[MIT-MC.ARPA].755421.851215.JAR>

    Date: Sun, 15 Dec 85 06:10:14 EST
    From: Alan Bawden <ALAN at MIT-MC.ARPA>

    ...

    Also a minor point about your quasi-quote proposal:  You notate the three
    magic objects that are used for recognition as #!QUASIQUOTE, #!UNQUOTE and
    #!UNQUOTE-SPLICE.  I claim that in a language specification it would be
    better to specify the names of three variables whose -values- are the three
    magic markers.  This is because it is dangerous for those objects to appear
    directly as constants in source code.  (In one message you point out this
    danger yourself, I seem to remember.)

    Instead of

	(IF (EQ? (CAR FORM) '#!UNQUOTE-SPLICE) ...)

    it is better to write

	(IF (EQ? (CAR FORM) UNQUOTE-SPLICE-MARKER) ...).

    And instead of

	(DEFINE-READER-SYNTAX #/`
	  (LAMBDA (STREAM)
	    `(#!QUASIQUOTE ,(READ STREAM))))

    (which doesn't work as intended) it is -certainly- better to write

	(DEFINE-READER-SYNTAX #/`
	  (LAMBDA (STREAM)
	    `(,QUASIQUOTE-MARKER ,(READ STREAM)))).

    In fact, I cannot imagine any situation in which I would want to type one
    of the three magic markers directly.  Conceivably a language specification
    should specify how the quasi-quote marker -looks-, so that you can
    recognize it if you happen to see it, but the user should not be encouraged
    to risk typing it in himself.  (Were I in charge I might consider
    specifying the names of the three variables, what the objects look like
    when PRINTed, and that is is an error if that printed representation is
    ever seen by READ.)

I definitely agree with most of this (I have run into exactly this bug,
and I suspect other people have too).  I only disagree with the
parenthetical remark at the end.  I think it's important that the
markers, or at least forms so marked, be rereadable.  One of the things
I was worried about was the problem of being able to print a program out
from one implementation and read it back in in another.  One solution
would be for PRINT to generate ` - , - ,@ syntax properly, and have
isolated occurences of the markers print nonrereadably.  Another
solution would be to require user code to always expand the backquote
form in some way before printing it, but that's unacceptable since your
target implementation might have some spiffy implementation of
backquote, and you'd like to be able to take advantage of it without
knowing what it is (or writing your own version of PRINT).

I tend to agree with Kent Dybvig's suggestion that the asymmetry with
QUOTE should be eliminated somehow.  I suggested a long time ago,
certainly on one of the T mailing lists and probably to the RRRS
authors, that 'FOO should read DIFFERENTLY from the list (QUOTE FOO),
either as a list with a funny marker in its CAR or as an object of a
different datatype, but no one seemed to like that suggestion.  Since
it's too late to change that, I think the markers should be symbols with
long names (no name is ever obscure enough, I know, but what can you
do?), since it's a pain both in some implementations and in the manual
to introduce new datatypes.  We would then have to agree on what the
name is, so that users can be sure to avoid using it.  Probably having
variables whose values are these symbols, or maybe even inventing little
S&ICP-style data abstractions (constructor, accessor, and predication
functions), is desirable too.  But that would be redundant, not
bare-bones the way the rest of scheme is...

∂20-Dec-85  1153	@MC.LCS.MIT.EDU:CPH@OZ.AI.MIT.EDU 	Editors used with Scheme 
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Dec 85  11:43:11 PST
Received: from OZ.AI.MIT.EDU by MC.LCS.MIT.EDU via Chaosnet; 20 DEC 85  14:22:18 EST
Date: Fri, 20 Dec 1985  14:17 EST
Message-ID: <CPH.12168673046.BABYL@MIT-OZ>
From: CPH%MIT-OZ@MIT-MC.ARPA
To:   Duke Briscoe <duke@MITRE.ARPA>
Cc:   SCHEME@MC.LCS.MIT.EDU
Subject: Editors used with Scheme
In-reply-to: Msg of 20 Dec 1985  13:37-EST from Duke Briscoe <duke at mitre.ARPA>

Folks around here seem to use Emacs almost exclusively.  I think that
most people find it pretty adequate, although, not being familiar with
the Interlisp structure editor, I may not know what I'm missing.

Perhaps your Emacs is deficient?  You mentioned mocklisp, which leads
me to believe that you are using Gosling Emacs.  If you are using BSD
Unix, maybe you should try GNU Emacs, which is available free and is
the best Emacs there is (Stallman wrote it).  If you try that and
still find it lacking, then perhaps Emacs implementors should make
some changes.

∂20-Dec-85  1153	@MC.LCS.MIT.EDU:duke@mitre.ARPA 	Editors used with Scheme   
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 20 Dec 85  11:42:53 PST
Received: from mitre.ARPA by MC.LCS.MIT.EDU 20 Dec 85 13:38:08 EST
Full-Name: DUKE BRISCOE
Message-Id: <8512201837.AA03811@mitre.ARPA>
Organization: The MITRE Corp., Washington, D.C.
To: SCHEME@MIT-MC
Subject: Editors used with Scheme
Date: 20 Dec 85 13:37:37 EST (Fri)
From: Duke Briscoe <duke@mitre.ARPA>

I'm not very happy using my version of Emacs with Scheme, because of 
deficiencies in the pretty printer and the general lack of commands
specialized for editing lisp.  What I would like would be a structure
editor like the one in Interlisp, along with the necessary integration
with a file package.  Does anybody have something like that?  Is 
everybody else using some version of Emacs or something similar?  Does
somebody have some huge amount of mocklisp code to make Emacs comparable
to the Interlisp structure editor?  I may attempt to put together a
structure editor in Scheme if I don't hear any satisfactory alternatives.

∂21-Jan-86  1150	@MC.LCS.MIT.EDU:marick%fang@gswd-vms 	Industrial-strength Scheme class.    
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 21 Jan 86  11:50:30 PST
Received: from gswd-vms.ARPA by MC.LCS.MIT.EDU 21 Jan 86 14:48:47 EST
Received: from fang.GSD (fang.ARPA) by gswd-vms.ARPA (5.9/5.6)
	id AA00332; Tue, 21 Jan 86 13:47:44 CST
Message-Id: <8601211947.AA00332@gswd-vms.ARPA>
Date: Tue, 21 Jan 86 13:45:09 cst
From: marick%fang@gswd-vms (Brian Marick)
To: scheme@mc.lcs.mit.edu
Subject: Industrial-strength Scheme class.

I am planning to teach a class in Scheme at work this summer.  I'll be using
←Structure and Interpretation of Computer Programs← and Indiana's version of
Scheme.  The people in the class will mostly be experienced C programmers,
along with a scattering of technical writers (with some Pascal experience)
and ex-programmers-now-managers.  I'm teaching the class to expose these
people to new styles of programming, styles that (I hope) are becoming
increasingly important.  I'm not an experienced teacher, though I have
taught such a classlet before.

Does anyone have any suggestions as to how I ought to go about this?  What
should I skim over?  What should I concentrate on?  Does the book contain
too much or too little to be covered in a summer, considering that the people
are experienced but also have full-time-or-more jobs?  How should I
supplement the book, and with what?  Thanks.

Brian Marick
Gould CSD - Urbana


∂21-Jan-86  1446	@MC.LCS.MIT.EDU:HAL%OZ.AI.MIT.EDU@XX.LCS.MIT.EDU 	Industrial-strength Scheme class.  
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 21 Jan 86  14:45:46 PST
Received: from OZ.AI.MIT.EDU by MC.LCS.MIT.EDU via Chaosnet; 21 JAN 86  17:42:37 EST
Date: Tue, 21 Jan 1986  17:41 EST
Message-ID: <HAL.12177098817.BABYL@MIT-OZ>
From: HAL%OZ.AI.MIT.EDU@XX.LCS.MIT.EDU
To:   marick%fang@GSWD-VMS.ARPA (Brian Marick)
Cc:   scheme@MC.LCS.MIT.EDU
Subject: Industrial-strength Scheme class.
In-reply-to: Msg of 21 Jan 1986  14:45-EST from marick%fang at gswd-vms (Brian Marick)


MIT runs summer courses in this material for industry types.  The
courses are two weeks of very intense full-time work.  If I were you,
I'd be really nervous about teaching this to people who are
simultaneously holding full-time jobs.  Given your goals, I would not
attempt to do more than the first 4 chapters.

It is VERY IMPORTANT that people do some programming, not just listen
to you lecture.  Contact McGraw-Hill and get hold of Julie Sussman's
instructor's manual for the course, which has some problem-set
material.

Good luck.

∂23-Jan-86  1301	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  Industrial-strength Scheme class.
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 23 Jan 86  13:01:09 PST
Received: from CSNET-RELAY.ARPA by MC.LCS.MIT.EDU 23 Jan 86 16:01:14 EST
Received: from indiana by csnet-relay.csnet id aj13046; 23 Jan 86 15:52 EST
Date: Thu, 23 Jan 86 15:45:07 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: scheme@mc.lcs.mit.edu
Subject: Re:  Industrial-strength Scheme class.

I think you might do well to look at the new "Little Lisper", by
Dan Friedman and Matthias Felleisen.  Every program seems to work
without modification in Chez Scheme, and I believe there is no
problem with other Schemes either (i.e., Scheme84, TIPC Scheme).

The Little Lisper starts out the way the old one did, teaching the
student about recursion, lists, etc.  But the new edition also
covers first-class functions, even going so far as to introduce
a "by-value" Y-combinator.  The code for a Scheme interpreter is
given in the book.

Assignments, continuations, and engines are not covered in the LL,
but that's alright since these topics are better left until after
you cover the material in the LL.  You should definitely cover set!
after you get through the LL.  As for continations and engines, I
find that people are able to pick up and enjoy engines in a short
time period, but that continuations confuse them.  So if you have
extra time left over, I would definitely cover engines.

I think the LL is more suited to a short class than the A&S text;
for a longer class I would cover the LL first, then A&S.  The LL
is also a "self-study" text, so that what you don't cover in class
the students can pick up easily on their own.

Dan may be able to tell you more about it (dfried@indiana).  I'm
sure that SRA would send you a copy if you tell them what you need
it for.

Kent Dybvig
dyb.indiana@csnet-relay (CSNET)
...!ihnp4!iuvax!dyb     (USENET)


∂24-Jan-86  0827	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	quasiquote implementation   
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 24 Jan 86  08:27:35 PST
Received: from CSNET-RELAY.ARPA by MC.LCS.MIT.EDU 24 Jan 86 10:49:26 EST
Received: from indiana by csnet-relay.csnet id a022299; 24 Jan 86 10:24 EST
Date: Fri, 24 Jan 86 01:01:14 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: rrrs-authors@mc.lcs.mit.edu
Subject: quasiquote implementation

Back when JAR first suggested making quasiquote standard, I transcribed
my quasiquote implementation from the C-coded reader into Scheme-coded
syntactic-extensions.  I promised to send the code to David Bartley at
TI and figured some of the rest of you might be interested as well.

I believe that this gives different results from JAR's, because it can
actually fold up explicit calls to "list" and "list*" (for better or for
worse).  It also insists that quasiquote, unquote, and unquote-splice
forms be well-formed, rather than ignoring those that aren't.  As with
JAR's, nested quasiquotes work properly.

Because quasiquote and company are expanded at compile time rather than
read time, it is reasonable to write code that produces quasiquote forms.  

"list*" (Common Lisp's name) is the same as JAR's "cons*".  The meaning
of everything else should be obvious.

(let ((check
         (lambda (x)
            (unless (and (pair? (cdr x)) (null? (cddr x)))
               (ferror (car x) "invalid form ~s" x)))))
   (define-macro! quasiquote (x)
      (recur f ((x x))
         (cond
            ((not (pair? x)) `',x)
            ((eq? (car x) 'quasiquote) (check x) (f (f (cadr x))))
            ((eq? (car x) 'unquote) (check x) (cadr x))
            ((eq? (car x) 'unquote-splice)
             (ferror 'unquote-splice "invalid context for ~s" x))
            ((and (pair? (car x)) (eq? (caar x) 'unquote-splice))
             (check (car x))
             (let ((d (f (cdr x))))
                (if (equal? d '(quote ()))
                    (cadar x)
                    `(append ,(cadar x) ,d))))
            (else
             (let ((a (f (car x))) (d (f (cdr x))))
                (if (pair? d)
                    (if (eq? (car d) 'quote)
                        (if (and (pair? a) (eq? (car a) 'quote))
                            `'(,(cadr a) . ,(cadr d))
                            (if (null? (cadr d))
                                `(list ,a)
                                `(list* ,a ,d)))
                        (if (memq (car d) '(list list*))
                            `(,(car d) ,a ,@(cdr d))
                            `(list* ,a ,d)))
                   `(list* ,a ,d))))))))

(define-macro! unquote (x)
   (ferror 'unquote
      "unquote form ,~s not valid outside of quasiquote"
      x))

(define-macro! unquote-splice (x)
   (ferror 'unquote
      "unquote-splice form ,@~s not valid outside of quasiquote"
      x))


∂24-Jan-86  1252	JAR@MC.LCS.MIT.EDU 	quasiquote implementation
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 24 Jan 86  12:52:38 PST
Date: Fri, 24 Jan 86 15:53:28 EST
From: Jonathan A Rees <JAR@MC.LCS.MIT.EDU>
Subject:  quasiquote implementation
To: dyb%indiana.csnet@CSNET-RELAY.ARPA
cc: RRRS-AUTHORS@MC.LCS.MIT.EDU
In-reply-to: Msg of Fri 24 Jan 86 01:01:14 est from Kent Dybvig <dyb%indiana.csnet at CSNET-RELAY.ARPA>
Message-ID: <[MC.LCS.MIT.EDU].794952.860124.JAR>

Your implementation, which is very similar to the T and MIT Scheme
quasiquote imeplementations, has the powerful advantage over mine of
conciseness, but it has the serious flaw that it makes the expansion of
nested quasiquote forms visible to the user, thus making it difficult to
write portable code to manipulates such forms.  For example, (EQUAL?
'`(A ,B) ``(A ,B)) doesn't hold in your implementation.  This seems to
defeat my original aim in suggesting that we standardize the external
syntax of `, which was to allow people to write portable
program-manipulating programs.

Jonathan

∂25-Jan-86  1155	@MC.LCS.MIT.EDU:dyb%indiana.csnet@CSNET-RELAY.ARPA 	Re:  quasiquote implementation   
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 25 Jan 86  11:55:21 PST
Received: from CSNET-RELAY.ARPA by MC.LCS.MIT.EDU 25 Jan 86 14:56:07 EST
Received: from indiana by csnet-relay.csnet id aa06542; 25 Jan 86 14:34 EST
Date: Sat, 25 Jan 86 13:04:04 est
From: Kent Dybvig <dyb%indiana.csnet@CSNET-RELAY.ARPA>
To: JAR@mc.lcs.mit.edu
Subject: Re:  quasiquote implementation
Cc: rrrs-authors@mc.lcs.mit.edu

    Your implementation, which is very similar to the T and MIT Scheme
    quasiquote imeplementations, has the powerful advantage over mine of
    conciseness, but it has the serious flaw that it makes the expansion of
    nested quasiquote forms visible to the user, thus making it difficult to
    write portable code to manipulates such forms.  For example, (EQUAL?
    '`(A ,B) ``(A ,B)) doesn't hold in your implementation.  This seems to
    defeat my original aim in suggesting that we standardize the external
    syntax of `, which was to allow people to write portable
    program-manipulating programs.
    
    Jonathan
    
Yes, I see what you mean.  My goal in making the forms standardized
was to to allow portable code such as an interpreter to make sense
out of what the function "read" returns, and also to provide for the
proper pretty-printing of source programs.  I hadn't thought of the
double-quasiquote issue.  When I read your first article, I thought
that you wanted

   '`(A ,B) = ``(A ,B) => (list (quote a) b)

which is relatively easy (but not desirable, since I didn't want to
reach inside the quote).  Instead, I see you want

   '`(A ,B) = ``(A ,B) => `(A ,B)

which I can certainly sympathize with.  This explains the need for
the "level" variable in your code.  For anyone who cares, here is
another (less powerful) version of my code  with a level-tracking
argument added.  I have tested it only briefly.

(let ((check
         (lambda (x)
            (unless (and (pair? (cdr x)) (null? (cddr x)))
                (ferror (car x) "invalid form ~s" x))))
      (quasicons
         (lambda (a d)
            (if (pair? d)
                (if (eq? (car d) 'quote)
                    (if (and (pair? a) (eq? (car a) 'quote))
                        `'(,(cadr a) . ,(cadr d))
                        (if (null? (cadr d))
                            `(list ,a)
                            `(list* ,a ,d)))
                    (if (memq (car d) '(list list*))
                        `(,(car d) ,a ,@(cdr d))
                        `(list* ,a ,d)))
                `(list* ,a ,d)))))
   (define-macro! quasiquote (x)
      (recur f ((x x) (n 0))
         (cond
            ((not (pair? x)) `',x)
            ((eq? (car x) 'quasiquote)
             (check x)
             (quasicons ''quasiquote (f (cdr x) (1+ n))))
            ((eq? (car x) 'unquote)
             (check x)
             (if (zero? n)
                 (cadr x)
                 (quasicons ''unquote (f (cdr x) (1- n)))))
            ((eq? (car x) 'unquote-splice)
             (check x)
             (if (zero? n)
                 (ferror 'unquote-splice "invalid context for ,@~s" (cadr x))
                 (quasicons ''unquote-splice (f (cdr x) (1- n)))))
            ((and (zero? n) (pair? (car x)) (eq? (caar x) 'unquote-splice))
             (check (car x))
             (let ((d (f (cdr x) n)))
                 (if (equal? d '(quote ()))
                     (cadar x)
                     `(append ,(cadar x) ,d))))
            (else (quasicons (f (car x) n) (f (cdr x) n)))))))

(define-macro! unquote (x)
   (ferror 'unquote
      "unquote form ,~s not valid outside of quasiquote"
      x))

(define-macro! unquote-splice (x)
   (ferror 'unquote
      "unquote-splice form ,@~s not valid outside of quasiquote"
      x))


∂28-Jan-86  1108	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Of growing code and diminishing hacks...    
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 28 Jan 86  10:52:57 PST
Received: from yale by MC.LCS.MIT.EDU 28 Jan 86 13:47:21 EST
Received: by Yale-Bulldog.YALE.ARPA; 28 Jan 86 06:22:59 EST (Tue)
Date: 28 Jan 86 06:22:59 EST (Tue)
From: <ram%YALE-RING@YALE.ARPA>
Message-Id: <8601281122.AA16563@Yale-Bulldog.YALE.ARPA>
Subject: Of growing code and diminishing hacks...
To: t-discussion@YALE.ARPA, scheme@mit-mc.arpa


    A SHORT BALLAD DEDICATED TO THE GROWTH OF PROGRAMS
    ==================================================
                      by
                  Ashwin Ram
    
    This is a tale of a sorry quest
    To master pure code at the T guru's behest
    I enrolled in a class that appealing did seem
    For it promised to teach fine things like T3 and Scheme
    
    The first day went fine; we learned of cells
    And symbols and lists and functions as well
    Lisp I had mastered and excited was I
    For to master T3 my hackstincts did cry
    
    I sailed through the first week with no problems at all
    And I even said "closure" instead of "function call"
    Then said the master that ready were we
    To start real hacking instead of simple theory
    
    Will you, said he, write me a function please
    That in lists would associate values with keys
    I went home and turned on my trusty Apollo
    And wrote a function whose definition follows:
    
        (cdr (assq key a-list))
    
    A one-liner I thought, fool that I was
    Just two simple calls without a COND clause
    But when I tried this function to run
    CDR didn't think that NIL was much fun
    
    So I tried again like the good King of yore
    And of code I easily generated some more:
    
        (cond ((assq key a-list) => cdr))
    
    It got longer but purer, and it wasn't too bad
    But then COND ran out and that was quite sad
        
    Well, that isn't hard to fix, I was told
    Just write some more code, my son, be bold
    Being young, not even a moment did I pause
    I stifled my instincts and added a clause
    
        (cond ((assq key a-list) => cdr)
              (else nil))
    
    Sometimes this worked and sometimes it broke
    I debugged and prayed and even had a stroke
    Many a guru tried valiantly to help
    But undefined datums their efforts did squelch.
    
    I returneth once more to the great sage of T
    For no way out of the dilemma I could see
    He said it was easy -- more lines must I fill
    with code, for FALSE was no longer NIL.
    
        (let ((val (assq key a-list)))
           (cond (val (cdr val))
                 (else nil)))
    
    You'd think by now I might be nearing the end
    Of my ballad which seems bad things to portend
    You'd think that we could all go home scot-free
    But COND eschewed VAL; it wanted #T
    
    So I went back to the master and appealed once again
    I said, pardon me, but now I'm really insane
    He said, no you're not really going out of your head
    Instead of just VAL, you must use NOT NULL instead
    
        (let ((val (assq key a-list)))
           (cond ((not (null? val)) (cdr val))
                 (else nil)))
    
    My song is over and I'm going home to bed
    With this ineffable feeling that I've been misled
    And just in case my point you have missed
    Somehow I preferred (CDR (ASSQ KEY A-LIST))
    
                        :-)    
    ==================================================


-------

∂28-Jan-86  2352	@MC.LCS.MIT.EDU:Miller.pa@Xerox.COM 	Re: Of growing code and diminishing hacks...    
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 28 Jan 86  23:52:17 PST
Received: from Xerox.COM by MC.LCS.MIT.EDU 29 Jan 86 02:52:42 EST
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JAN 86 23:49:12 PST
Date: 28 Jan 86 23:36 PST
From: Miller.pa@Xerox.COM
Subject: Re: Of growing code and diminishing hacks...
In-reply-to: <ram%YALE-RING@YALE.ARPA>'s message of 28 Jan 86 06:22:59
 EST (Tue)
To: ram%YALE-RING@YALE.ARPA
cc: t-discussion@YALE.ARPA, scheme@MC.LCS.MIT.EDU
Message-ID: <860128-234912-1014@Xerox>

(define (overloaded-cdr val)
	(if (null? val) nil (cdr val)))

(overloaded-cdr (assq key a-list))


	In other words, if you want a cdr that horribly overloads nil, then
write one.  As for me, I think of a cons cell as an object with car and
cdr fields in it, just as a point is an object with x and y fields in
it.  How about:

(define (overloaded-x point)
	(if (null? point) nil (x point)))


∂29-Jan-86  0121	@MC.LCS.MIT.EDU:Miller.pa@Xerox.COM 	Re: Of growing code and diminishing hacks...    
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 29 Jan 86  01:21:31 PST
Received: from Xerox.COM by MC.LCS.MIT.EDU 29 Jan 86 04:21:45 EST
Received: from Salvador.ms by ArpaGateway.ms ; 29 JAN 86 01:20:42 PST
Date: 29 Jan 86 01:14 PST
From: Miller.pa@Xerox.COM
Subject: Re: Of growing code and diminishing hacks...
In-reply-to: <ram%YALE-RING@YALE.ARPA>'s message of 28 Jan 86 06:22:59
 EST (Tue)
To: ram%YALE-RING@YALE.ARPA
cc: t-discussion@YALE.ARPA, scheme@MC.LCS.MIT.EDU
Message-ID: <860129-012042-1051@Xerox>

	And another thing.  The only reason NIL == #F usually works out so well
in lisps is that the most common domain of concern is lists.  In both C
and APL, FALSE == 0 since a very common domain of concern is numbers.
Hopefully we are moving towards a programming style that is more
abstract datatype or object based, and so the primacy of lists will
diminish.  In any case, I don't want my programming language prejudging
for me what types of object should be my major concern, and compromising
its foundations to optimize for that one type.

∂29-Jan-86  0558	GJC@MC.LCS.MIT.EDU 	Overloading of empty list as false.
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 29 Jan 86  05:58:17 PST
Date: Wed, 29 Jan 86 08:58:51 EST
From: "George J. Carrette" <GJC@MC.LCS.MIT.EDU>
Subject:  Overloading of empty list as false.
To: Miller.pa@XEROX.COM
cc: SCHEME@MC.LCS.MIT.EDU, t-discussion@YALE.ARPA,
    ram@YALE-RING.ARPA
In-reply-to: Msg of 29 Jan 86 01:14 PST from Miller.pa at Xerox.COM
Message-ID: <[MC.LCS.MIT.EDU].800287.860129.GJC>

The primacy of lists in lisp is due to the fact that lisp is its own
meta language and the vocabulary of that meta language is constructed
inductively from lists, symbols and other constants.  Furthermore, the
most general graphs can be constuctured entirely in terms of
bifurcations represented as cons cells; and bifurcations have a
primacy over trifurcations etc. Topping this off by using the logical falsity
constant as the token to mark the end of certain kinds of graphs is
entirely natural definition to use.

The lists themeselves will remain in their primacy as a prefered construct of
efficient assembly language programming, (especially if this means your
assembly language is LISP on a LISPMACHINE). Take note Plummer's multilisp
emulator that he implemented on the 3600: Comments in the code indicating that
using (SETQ *STACK* (CONS ELEMENT *STACK*)) was more efficient than
using the C/FORTRAN/PASCAL style INDEX plus ARRAY, because the GC overhead
was smaller than the expense of the extra instructions and memory references
needed to manipulate the more complicated data structure.

But I am arguing the barn door closed after the cows have left.
The recent slant of revised-revised-report-on-scheme has
indeed cleaned up things to make them more acceptable to the
general community; throwing out all the obvious meta language
machinery and with it much of the preference for lists.

The reason that FALSE == 0 in C is not due to the concern for the domain
of numbers. (Since in C one will often mark the end of character strings
with 0, and represent the NULL pointer as 0 also). FALSE == 0 because
of the instruction sets and memory organizations of the machines
on which C was developed. Similarly in PDP10 Maclisp and CADR Lispmachine
NIL == 0 (as a machine location address).


∂29-Jan-86  1049	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Re: Of growing code and diminishing hacks...
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 29 Jan 86  10:49:09 PST
Received: from yale by MC.LCS.MIT.EDU 29 Jan 86 13:05:55 EST
Received: by Yale-Bulldog.YALE.ARPA; 29 Jan 86 09:39:05 EST (Wed)
Date: 29 Jan 86 09:39:05 EST (Wed)
From: <ram%YALE-RING@YALE.ARPA>
Message-Id: <8601291439.AA10931@Yale-Bulldog.YALE.ARPA>
Subject: Re: Of growing code and diminishing hacks...
To: <Miller.pa@Xerox.COM>
Cc: t-discussion@YALE.ARPA, scheme@mit-mc.arpa
In-Reply-To: <Miller.pa@Xerox.COM>, 28 Jan 86 23:36 PST

    (define (overloaded-cdr val)
    	(if (null? val) nil (cdr val)))
    
    (overloaded-cdr (assq key a-list))
    
    
    	In other words, if you want a cdr that horribly overloads nil, then
    write one.  As for me, I think of a cons cell as an object with car and
    cdr fields in it, just as a point is an object with x and y fields in
    it.  How about:
    
    (define (overloaded-x point)
    	(if (null? point) nil (x point)))
    
    
    
So  now  we  have a proliferation of functions.  You could just as well think
of CAR and CDR as operations, and NIL as  an  object  that  handles  them  by
returning  NIL.  Much cleaner.  Well, maybe not; I guess that's debatable.  I
think the code is cleaner even though the semantics that  the  compiler  must
implement  may  become  a  little hairier.  But that's what compilers are for
:-). 




-------

∂29-Jan-86  1119	@MC.LCS.MIT.EDU:ram%YALE-RING@YALE.ARPA 	Re: Of growing code and diminishing hacks...
Received: from MC.LCS.MIT.EDU by SU-AI.ARPA with TCP; 29 Jan 86  11:19:22 PST
Received: from yale by MC.LCS.MIT.EDU 29 Jan 86 13:19:18 EST
Received: by Yale-Bulldog.YALE.ARPA; 29 Jan 86 09:49:57 EST (Wed)
Date: 29 Jan 86 09:49:57 EST (Wed)
From: <ram%YALE-RING@YALE.ARPA>
Message-Id: <8601291449.AA11227@Yale-Bulldog.YALE.ARPA>
Subject: Re: Of growing code and diminishing hacks...
To: <Miller.pa@Xerox.COM>
Cc: t-discussion@YALE.ARPA, scheme@mit-mc.arpa
In-Reply-To: <Miller.pa@Xerox.COM>, 29 Jan 86 01:14 PST

    	And another thing.  The only reason NIL == #F usually works out so well
    in lisps is that the most common domain of concern is lists.  In both C
    and APL, FALSE == 0 since a very common domain of concern is numbers.


I didn't say that NIL was in any way the best choice for FALSE across all
languages.  In Lisps, NIL = #F is just as reasonable as 0 = FALSE in C or
APL.  Try telling a C programmer that 0 won't be FALSE anymore. 
-------